如您所见,这在这些情况下不起作用,因为在编译时,必须确保在使用 struct/enum/class 之前初始化所有属性。
您可以要求另一个初始化程序,以便编译器知道所有属性都已初始化:
protocol Car {
var wheels : Int { get set }
// make another initializer
// (which you probably don't want to provide a default implementation)
// a protocol requirement. Care about recursive initializer calls :)
init()
init(wheels: Int)
}
extension Car {
// now you can provide a default implementation
init(wheels: Int) {
self.init()
self.wheels = wheels
}
}
// example usage
// mark as final
final class HoverCar: Car {
var wheels = 0
init() {}
}
let drivableHoverCar = HoverCar(wheels: 4)
drivableHoverCar.wheels // 4
从 Xcode 7.3 beta 1 开始,它可以structs
按预期使用,但不能与类一起使用,因为如果它们不在协议中是 afinal
并且它可以被覆盖,因此它不能通过扩展添加。解决方法(正如编译器建议的那样):将.init(wheels: Int)
required init
class
final
另一种解决方法(深入;没有final class
)
要使用类而不使它们成为最终的,您还可以删除init(wheels: Int)
协议中的要求。看起来它的行为与以前没有什么不同,但请考虑以下代码:
protocol Car {
var wheels : Int { get set }
init()
// there is no init(wheels: Int)
}
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
}
}
// prints "HoverCar"
let drivableHoverCar = HoverCar(wheels: 4)
func makeNewCarFromCar<T: Car>(car: T) -> T {
return T(wheels: car.wheels)
}
// prints "Extension"
makeNewCarFromCar(drivableHoverCar)
因此,如果您Car
从通用上下文中创建一个,其中您调用的类型init
仅被称为Car
扩展初始化程序,即使初始化程序是在HoverCar
. 这只是因为协议中没有init(wheels: Int)
要求而发生。
如果添加它,则在声明class
as时会遇到前一个问题,final
但现在它会打印两次“HoverCar”。无论哪种方式,第二个问题可能永远不会发生,因此它可能是一个更好的解决方案。
旁注:如果我犯了一些错误(代码、语言、语法……),欢迎您纠正我:)