我在一个 Swift playground 中有以下示例,试图在 Swift 中实现复制构造函数:
class Shape : NSObject {
var color : String
override init() {
color = "Red"
}
init(copyFrom: Shape) {
color = copyFrom.color
}
}
class Square : Shape {
var length : Double
override init() {
super.init()
length = 10.0
}
init(copyFrom: Square) { /* Compilation error here! */
super.init(copyFrom: copyFrom)
length = copyFrom.length
}
}
let s : Square = Square() // {{color "Red"} length 10.0}
let copy = Square(copyFrom: s) // {{color "Red"} length 10.0}
s.color = "Blue" // {{color "Blue"} length 10.0}
s // {{color "Blue"} length 10.0}
copy // {{color "Red"} length 10.0}
问题在于,这段代码在当前形式下实际上无法编译。在Square
子类的init(copyFrom: Square)
方法中,会报告以下错误:
覆盖具有选择器 'initWithCopyFrom:' 的方法的类型不兼容 '(Square) -> Square'
如果这不是一个构造函数,而是一个普通的func
,那么这个问题就有意义了,因为你可能会传入一个预期在超类中的类型,在子类中已被重写为更严格的类型:
let mySquare : Shape = Square() // Note the var is a SHAPE
mySquare.someShapeMethod("Test") // If Square overrides someShapeMethod() to expect Int, compiler errors out to protect us here.
但它是一个构造函数,这使我相信我应该能够重写它并提供不同的方法签名,因为在编译时绝对知道对象的类型。
如果我修改Shape
以不再扩展NSObject
,则此问题消失。 但是,由于与现有的Objective-C代码一起使用,它需要扩展NSObject
。
如何更新我的拷贝构造函数以允许Shape
知道它正在从Shape
复制,并允许Square
知道它正在从Square
复制?
let theCopy = self.dynamicType.init()
,当然要使用as!
而不是as
(仅提及,因为这里出现了相关的问题:https://dev59.com/F43da4cB1Zd3GeqP5t50)。 - Martin RNS_UNAVAILABLE
是 Objective-C 中避免继承初始化方法的一种方式,这与不继承它非常相似。但可能是在此答案之后发布的。 - Tommy