我正在用 Kotlin 测试一些东西,现在如果我找不到答案,我将无法正常休眠。
看看这个类:
data class Person(
val name: String,
val age: Int? = 0
) {
constructor(
secondName: String,
secondAge: Int = 5
) : this(
name = "$secondName 2",
age = secondAge
)
}
fun main() {
val firstCase = Person("Lorem") // Complaints about ambiguity.
val secondCase = Person("Lorem", 42) // Calls secondary constructor.
}
提示第一个案例中的歧义是可以理解的,但为什么第二个案例中没有出现同样的情况呢?为什么它决定调用辅助构造函数而不是主构造函数?
现在,如果我在主构造函数上添加另一个参数具有默认值:
data class Person(
val name: String,
val age: Int? = 0,
val isAdult: Boolean = false
) {
constructor(
secondName: String,
secondAge: Int = 5
) : this(
name = "$secondName 2",
age = secondAge
)
}
fun main() {
val thirdCase = Person("Lorem") // Calls secondary constructor.
}
我原以为第三个案例会有歧义,就像第一个案例一样。但不是!它调用辅助构造函数。为什么?!
最佳答案
method resolution的规则在 Kotlin(和 Java)中可能有点神秘。值得庆幸的是,他们几乎在所有情况下都会做显而易见的事情——这显然是重点! — 但也有一些令人惊讶的极端情况。
一般原则是它选择可以匹配的最具体方法,并且只有在没有一个获胜者时才给出错误。
所以在第二种情况下,参数是 String
和 Int
。候选者是主构造函数(采用 String
和 Int?
)和次构造函数(采用 String
和 Int
>).后者是更具体的匹配,因为 Int
是 Int?
的子类型,所以它选择那个。
但在您的第一种情况下,提供的唯一参数是一个 String
,它与两个构造函数均等匹配,因此没有明确的赢家,它会标记出歧义。
你的第三个案例就更不明显了。然而,section of the Kotlin spec讨论如何从所有重载中选择最具体的候选人说:
For each candidate we count the number of default parameters not specified in the call (i.e., the number of parameters for which we use the default value). The candidate with the least number of non-specified default parameters is a more specific candidate
我认为这就是您的第三种情况发生的情况:它选择辅助构造函数(它将只保留一个具有默认值的参数)而不是主要构造函数(将保留两个参数)。
https://stackoverflow.com/questions/70626050/