我在Swift游乐场中有以下示例,试图在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}
Run Code Online (Sandbox Code Playgroud)
问题是,这实际上并没有以其当前形式进行编译.在子类中的init(copyFrom: Square)
方法,Square
报告此错误:
Overriding method with selector 'initWithCopyFrom:' has incompatible type '(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.
Run Code Online (Sandbox Code Playgroud)
但它是一个构造函数的事实让我相信我应该能够覆盖它并提供不同的方法签名,因为它在编译时绝对知道对象的类型是什么.
如果我Shape
改为不再延伸,这个问题就会消失NSObject
.但是,由于包含现有的Objective-C代码,因此需要进行扩展NSObject
.
如何更新我的复制构造函数以允许Shape
知道它从a复制Shape
,并允许Square
知道它是从Square
?复制?
Rob*_*ier 23
init(copyFrom: Square)
是一个重载,而不是重写init(copyFrom: Shape)
.我的意思是它们是不相关的方法,因为它们接受不同的类型.在斯威夫特这是可以接受的.在ObjC,这是非法的.ObjC没有重载.
Swift初始化程序不会自动继承.所以在Swift中,你无法尝试将随机副本复制Shape
为Square
.初始化程序不可用.但是在ObjC中,初始化器会自动继承(并且你无法阻止它们这样做).因此,如果您有方法initWithCopyFrom:(*Shape)
,则需要每个子类都愿意接受它.这意味着您可以(在ObjC中)尝试创建Circle的副本作为Square.那当然是胡说八道.
如果这是一个NSObject
子类,您应该使用NSCopying
.以下是你将如何做到这一点:
import Foundation
class Shape : NSObject, NSCopying { // <== Note NSCopying
var color : String
required override init() { // <== Need "required" because we need to call dynamicType() below
color = "Red"
}
func copyWithZone(zone: NSZone) -> AnyObject { // <== NSCopying
// *** Construct "one of my current class". This is why init() is a required initializer
let theCopy = self.dynamicType()
theCopy.color = self.color
return theCopy
}
}
class Square : Shape {
var length : Double
required init() {
length = 10.0
super.init()
}
override func copyWithZone(zone: NSZone) -> AnyObject { // <== NSCopying
let theCopy = super.copyWithZone(zone) as Square // <== Need casting since it returns AnyObject
theCopy.length = self.length
return theCopy
}
}
let s = Square() // {{color "Red"} length 10.0}
let copy = s.copy() as Square // {{color "Red"} length 10.0} // <== copy() requires a cast
s.color = "Blue" // {{color "Blue"} length 10.0}
s // {{color "Blue"} length 10.0}
copy // {{color "Red"}
Run Code Online (Sandbox Code Playgroud)
斯威夫特3
class Shape: NSObject, NSCopying {
required override init() {
super.init()
}
func copy(with zone: NSZone? = nil) -> Any {
let copy = type(of: self).init()
return copy
}
}
class Square: Shape {
required override init() {
super.init()
}
func copy(with zone: NSZone? = nil) -> Any {
let copy = super.copy(with: zone) as! Square
copy.foo = self.foo
......
return copy
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
11999 次 |
最近记录: |