kotlin - 为什么 Kotlin 不提示歧义?为什么要调用辅助构造函数?

我正在用 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)中可能有点神秘。值得庆幸的是,他们几乎在所有情况下都会做显而易见的事情——这显然是重点! — 但也有一些令人惊讶的极端情况。

一般原则是它选择可以匹配的最具体方法,并且只有在没有一个获胜者时才给出错误。

所以在第二种情况下,参数是 StringInt。候选者是主构造函数(采用 StringInt?)和次构造函数(采用 StringInt >).后者是更具体的匹配,因为 IntInt? 的子类型,所以它选择那个。

但在您的第一种情况下,提供的唯一参数是一个 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/

相关文章:

reactjs - 为什么箭头函数可以工作但常规函数不能 React JS

csv - 如何使用 bash 中的 awk 删除具有相似数据的行以仅保留特定列(tsv 文件)中的

python - 如何阻止 Selenium 在执行期间关闭驱动程序?

r - 如何通过合并 csv 文件创建数据框,然后基于它创建 Shiny 的应用程序?

r - 如何根据特定行的比较来消除变量

c++ - 如何保证使用编译时常量初始化堆栈变量

go - 我应该如何使用 protoc-gen-go-grpc?

html - 使用圆形元素的饼图

c++ - 如何检查两个数组或列表是否相同?

c - 如何跟踪全局变量重新定义问题的链接器问题