考虑以下代码:
class Foo(val bar: String, val baz: Boolean = true) {
constructor(bar: String) : this(bar, false)
}
Run Code Online (Sandbox Code Playgroud)
无需添加辅助构造函数,我就可以调用,Foo("")因为第二个参数具有默认值。这将导致baz是true。
添加辅助构造函数后,我仍然可以调用Foo(""),除了现在baz是false。
为什么 Kotlin 不认为这是重复的构造函数签名,因为它们都可以用相同的参数调用?
如果你看一下字节码,实际上生成了三个构造函数,正如 Roland 已经指出的那样。
public Foo(@NotNull String bar, boolean baz) { ... }
public Foo(String var1, boolean var2, int var3, DefaultConstructorMarker var4) { ... }
public Foo(@NotNull String bar) { ... }
Run Code Online (Sandbox Code Playgroud)
因此,没有重复的构造函数签名。现在有人可能会问 Kotlin 如何选择仅从调用站点判断的重载。
总体原理是将从重载候选中选择最具体的函数/构造函数。
Kotlin 语言规范是这样说的:
对于每个候选,我们计算调用中未指定的默认参数的数量(即我们使用默认值的参数数量);
具有最少数量的非指定默认参数的候选者是更具体的候选者;
我知道您希望这只是一个例子,但如果在现实世界中发生这样的事情,应该避免它,就像Kotlin 语言文档(第 76 页)所述:
如果您有一个具有多个重载构造函数的对象,这些构造函数不调用不同的超类构造函数,并且不能简化为具有默认参数值的单个构造函数,那么最好将重载的构造函数替换为工厂函数。
class Foo2(val bar: String, val baz: Boolean = true) {
companion object {
fun factoryCreate(s: String) = Foo2(s, false)
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,创建之后的内容总是很清楚(无需考虑重载解析规则)baz。
| 归档时间: |
|
| 查看次数: |
868 次 |
| 最近记录: |