protocol EmptyInitializable {
init()
}
@propertyWrapper
struct PropertyWrapper: EmptyInitializable {
let wrappedValue: Int
init(_ wrappedValue: Int = 0) {
self.wrappedValue = wrappedValue
}
}
// This one lools redundent
extension PropertyWrapper {
public init() {
wrappedValue = 0
}
}
为什么我们需要在底部进行扩展?为什么编译器不能弄清楚,它struct PropertyWrapper
已经符合 的要求protocol EmptyInitializable
?看起来好丑啊...
PS我相信它以前确实在类似的情况下起作用过。
编译器不会降低
到
因为除其他原因外,编译器必须为每个可选参数生成的重载数量呈指数增长。对于具有 5 个可选参数的方法,编译器需要生成 32 个不同的签名。
话虽如此,
PropertyWrapper
显然不符合EmptyInitializable
。实际发生的情况是,只有一个重载,但对于每个可选参数,都会生成一个 thunk 来计算该参数的值。
当调用者未提供所有参数时,还有一些元数据告诉编译器生成对该 thunk 的调用。呼叫
PropertyWrapper()
降低至PropertyWrapper(defaultValueForArgument0OfInit())
。您可以在godbolt.org中查看编译后的代码。如果通过协议调用
init
,则调用是动态调度的,因此编译器甚至不知道将调用哪个实现,更不用说是否需要传递可选参数的默认值了。当然,编译器可以以其他方式设计,使之成为可能,但询问为什么它没有以这些方式设计,并不能真正回答,除非你非常具体。
旁注:由于您仅为可以在没有参数的情况下初始化的类型创建了一个协议,因此我建议阅读Protocols are more than Bags of Syntax。