如您所见,在这种情况下,这是行不通的,因为在编译时,必须确保在使用结构体/枚举/类之前初始化所有属性。
您可以将另一个初始化程序作为要求,以便编译器知道所有属性都已初始化:
protocol Car {
var wheels : Int { get set }
init()
init(wheels: Int)
}
extension Car {
init(wheels: Int) {
self.init()
self.wheels = wheels
}
}
final class HoverCar: Car {
var wheels = 0
init() {}
}
let drivableHoverCar = HoverCar(wheels: 4)
drivableHoverCar.wheels
自从Xcode 7.3 beta 1版本以来,它可以按预期与
structs
一起使用,但对于类而言则不是这样,因为如果它们不是
final
,那么协议中的
init(wheels: Int)
将成为必需的初始化程序,并且它可以被覆盖,因此不能通过扩展添加。解决方法(正如编译器所建议的):使
class
变为
final
。
另一个解决方法(详细说明;没有
final class
):
要处理类而不使它们变为final,您还可以在协议中删除
init(wheels: Int)
的要求。它似乎与以前没有什么不同,但请考虑以下代码:
protocol Car {
var wheels : Int { get set }
init()
}
extension Car {
init(wheels: Int) {
self.init()
print("Extension")
self.wheels = wheels
}
}
class HoverCar: Car {
var wheels = 0
required init() {}
init(wheels: Int) {
print("HoverCar")
self.wheels = wheels
}
}
let drivableHoverCar = HoverCar(wheels: 4)
func makeNewCarFromCar<T: Car>(car: T) -> T {
return T(wheels: car.wheels)
}
makeNewCarFromCar(drivableHoverCar)
如果你从一个通用的上下文中创建一个Car
,并且在调用init
时只知道它是Car
类型,则即使在HoverCar
中定义了一个初始化程序,在扩展初始化程序也会被调用。这仅发生在协议中没有init(wheels: Int)
要求的情况下。
如果添加它,您将面临以前使用final
关键字声明该class
的问题,但现在它会打印两次"HoverCar"。无论哪种方式,第二个问题可能永远不会发生,因此它可能是更好的解决方案。
附注:如果我犯了一些错误(代码、语言、语法等),欢迎您指正 :)