Kotlin allows to name a function same as an existing class, e.g. HashSet
with initializer function could be implemented like this:
fun <T> HashSet(n : Int, fn: (Int) -> T) = HashSet<T>(n).apply {
repeat(n) {
add(fn(it))
}
}
When used, it looks like a normal HashSet
constructor:
var real = HashSet<String>()
var fake = HashSet(5) { "Element $it" }
Should this be avoided or encouraged and why?
UPD
In the updated coding conventions, there's a section on this topic:
The motivation I described below, though, seems to still hold.
As said in documentation about the naming style:
One strong reason to avoid naming a function same to a class is that it might confuse a developer who will use it later, because, contrary to their expectations:
open
)new HashSet(n, it -> "Element " + it)
is an error)HashSet(n) { "Element $it" }
will construct not aHashSet
but, for example, aLinkedHashSet
It's better to show it explicitly that it's a factory function, not a constructor, to avoid this confusion.
Naming a function same to a class is generally avoided in stdlib, too. Given
SomeClass
, in stdlib a preferred naming style for factory functions issomeClassOf
,someClassBy
or whatever explains the semantics of the function best. The examples:generateSequence { ... }
andsequenceOf(...)
lazy { ... }
andlazyOf(...)
compareBy { ... }
listOf(...)
,setOf(...)
,mapOf(...)
So, one should definitely have strong reason to have a function mimic a constructor.
Instead, a function's name might tell a user more (even everything) about its usage.
I agree with +hotkey. It's probably best to avoid confusion in this case.
If it's only used internally and all the other devs (if any) are okay with it, though, I'd say to go for it. Python acknowledges that idea and I love it. Heck, they go both ways, being okay with you naming a class in function case, too, if it feels more like it's acting like a function. But, Python doesn't have to deal with Java interop, so definitely don't do it for public code.