我们是否应避免在Kotlin中命名与现有类相同的函数? 为什么?
Kotlin允许命名与现有类相同的函数,例如HashSet
具有初始化函数可以像这样实现:
fun HashSet(n : Int, fn: (Int) -> T) = HashSet(n).apply { repeat(n) { add(fn(it)) } }
使用时,它看起来像一个正常的HashSet
构造函数:
var real = HashSet() var fake = HashSet(5) { "Element $it" }
这应该避免或鼓励,为什么?
UPD
在更新的编码惯例中,有一个关于这个主题的部分 :
工厂function
如果你为一个类声明一个工厂函数,避免给它和类本身一样的名字。 更喜欢使用明确的名称,明确为什么工厂function的行为是特殊的。 只有在没有特别的语义时,才可以使用与该类相同的名称。
例:
class Point(val x: Double, val y: Double) { companion object { fun fromPolar(angle: Double, radius: Double) = Point(...) } }
但是我下面描述的动机似乎依然存在。
正如在有关命名风格的文档中所述:
如果有疑问,请默认Java代码约定,例如:
- 方法和属性以小写开头
避免命名与类相同的function的一个强有力的理由是,它可能会混淆后面将使用它的开发者,因为违背了他们的期望:
- 该函数将不可用于超级构造函数调用(如果该类是
open
) - 它不会通过reflection作为构造函数来显示
- 它将不能用作Java代码中的构造函数(
new HashSet(n, it -> "Element " + it)
是一个错误) - 如果你想稍后改变实现并返回一些子类实例,它会变得更混乱,
HashSet(n) { "Element $it" }
将不会构造HashSet
但是,例如LinkedHashSet
为了避免这种混淆,最好明确地说明它是一个工厂函数而不是构造函数。
在stdlib中通常也可以避免命名与类相同的函数。 给定SomeClass
,在stdlib中,工厂函数的首选命名风格是someClassOf
, someClassBy
或其他解释函数的最佳语义。 例子:
-
generateSequence { ... }
和sequenceOf(...)
-
lazy { ... }
和lazyOf(...)
-
compareBy { ... }
-
listOf(...)
,listOf(...)
,setOf(...)
mapOf(...)
所以,应该有一个强有力的理由来有一个function模仿一个构造函数。
相反,函数的名称可能会告诉用户更多(甚至是全部)关于它的用法。
我同意+热键。 在这种情况下最好避免混淆。
如果只是在内部使用,而其他所有的开发者(如果有的话)都可以使用,但是我想要去做。 Python承认这个想法,我喜欢它。 哎呀,他们是双向的,如果你觉得它更像是一个函数,你也可以在函数的情况下命名一个类。 但是,Python不必处理Java互操作,所以绝对不要用于公共代码。