考虑以下代码:
class Foo(val bar: String, val baz: Boolean = true) {
constructor(bar: String) : this(bar, false)
}
在不添加辅助构造函数的情况下,我可以调用Foo("")
,因为第二个参数具有默认值。这将导致baz
是true
。
除了第二个构造函数之外,我仍然可以调用Foo("")
,除了现在baz
是false
。
为什么Kotlin不会将其视为重复的构造函数签名,因为它们都可以使用相同的参数来调用?
答案 0 :(得分:4)
正如Roland所指出的那样,如果看一下字节码,实际上生成了三个构造函数。
public Foo(@NotNull String bar, boolean baz) { ... }
public Foo(String var1, boolean var2, int var3, DefaultConstructorMarker var4) { ... }
public Foo(@NotNull String bar) { ... }
因此,没有重复的构造函数签名。现在,人们可能会问Kotlin如何选择仅从呼叫站点来判断哪个过载。
总体理由是,将从重载候选中选择最具体的函数/构造函数。
这是Kotlin language specification所说的:
对于每位候选人,我们计算通话中未指定的默认参数的数量(即,我们使用的默认参数的数量) 默认值);
未指定默认参数最少的候选人是更具体的候选人;
我知道您只是想举一个例子,但是如果在现实情况下发生这种情况,应该避免使用Kotlin Language Documentation(第76页)状态:
如果您的对象具有多个重载的构造函数,而这些构造函数没有 调用不同的超类构造函数,并且不能简化为 具有默认参数值的单个构造函数,建议替换为 具有工厂功能的重载构造函数。
class Foo2(val bar: String, val baz: Boolean = true) {
companion object {
fun factoryCreate(s: String) = Foo2(s, false)
}
}
在这种情况下,始终会很清楚(无需考虑重载解决方案规则)创建后baz
是什么。