我们应该避免在Kotlin中命名与现有类相同的函数吗?为什么?

Vil*_*kas 8 kotlin kotlin-extension

Kotlin允许命名一个与现有类相同的函数,例如HashSet初始化函数可以像这样实现:

fun <T> HashSet(n : Int, fn: (Int) -> T) = HashSet<T>(n).apply {
    repeat(n) {
        add(fn(it))
    }
}
Run Code Online (Sandbox Code Playgroud)

使用时,它看起来像一个普通的HashSet构造函数:

var real = HashSet<String>()
var fake = HashSet(5) { "Element $it" }
Run Code Online (Sandbox Code Playgroud)

这应该避免或鼓励,为什么?

hot*_*key 14

UPD

在更新的编码约定中,有关于此主题部分:

工厂功能

如果为类声明工厂函数,请避免为其赋予与类本身相同的名称.首选使用不同的名称,明确为什么工厂函数的行为是特殊的.只有在没有特殊语义的情况下,才能使用与该类相同的名称.

例:

class Point(val x: Double, val y: Double) {
    companion object {
        fun fromPolar(angle: Double, radius: Double) = Point(...)
    }
}
Run Code Online (Sandbox Code Playgroud)

不过,我下面描述的动机似乎仍然存在.


正如关于命名风格的文档中所述:

如果有疑问,默认为Java编码约定,例如:

  • 方法和属性以小写字母开头

避免将一个函数命名为类的一个强有力的理由是,它可能会混淆将在以后使用它的开发人员,因为,与他们的期望相反:

  • 该函数将不可用于超级构造函数调用(如果类是open)
  • 它不会通过反射作为构造函数可见
  • 它不能用作Java代码中的构造函数(new HashSet(n, it -> "Element " + it)是一个错误)
  • 如果你想稍后改变实现并返回一些子类实例,它会变得更加混乱,HashSet(n) { "Element $it" }构造不是一个HashSet但是,例如,LinkedHashSet

最好明确地说明它是一个工厂函数,而不是构造函数,以避免这种混淆.

在stdlib中通常也避免将一个函数命名为类.给定SomeClass,在stdlib中,工厂函数的首选命名方式是someClassOf,someClassBy或者最好地解释函数的语义.例子:

  • generateSequence { ... }sequenceOf(...)
  • lazy { ... }lazyOf(...)
  • compareBy { ... }
  • listOf(...),setOf(...),mapOf(...)

因此,人们应该有充分的理由让函数模仿构造函数.

相反,函数的名称可能会告诉用户更多(甚至一切)有关其用法的信息.

  • 作为负责Kotlin文档的开发人员,我发现这个答案是非常明智的指导.没有理由更喜欢辅助构造函数到工厂函数,但是当你使用工厂函数时,如果你给它们不同的名称,代码就更清楚了,不同于类的名称. (6认同)