我在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}
问题在于这实际上并不能以当前形式进行编译。在子类中的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.
但是事实是它是 构造函数 ,这使我相信我应该能够重写它并提供不同的方法签名,因为在编译时绝对知道对象的类型是什么。
如果我更改Shape
为不再扩展,此问题将消失NSObject
。但是,由于包含在现有的Objective-
C代码中,因此需要对其进行扩展NSObject
。
如何更新我的复制构造函数,以允许a Shape
知道从a复制Shape
,而允许a Square
知道从a复制Square
?
init(copyFrom: Square)
是的重载,而不是覆盖init(copyFrom: Shape)
。我的意思是,它们是不相关的方法,因为它们接受不同的类型。在Swift中这是可以接受的。在ObjC中,这是非法的。ObjC中没有重载。
Swift初始化器不会自动继承。因此,在Swift中,您不能尝试将random复制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"}
迅捷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
}
}
问题内容: 我想在BaseClass构造函数中复制SubClass对象。我需要以下代码正确执行。 可能吗?如果可以,我该怎么办?其他如何获得类似的效果? 问题答案: 这是不可能的。类A的构造函数为您提供了A的实例,无法绕开它。为什么不显式实例化子类? 另一种可能性可能涉及静态工厂方法,例如:
问题内容: python中是否有复制构造函数?如果没有,我将怎么做才能达到类似的目的? 情况是,我正在使用一个库,并且在其中扩展了其中一个类,并提供了额外的功能,我希望能够将从库中获得的对象转换为自己的类的实例。 问题答案: 我想你想要复制模块 您可以像控制泡菜一样控制复印。
问题内容: 我有一个定义抽象方法的抽象类A。这意味着,要使一个类变得可实例化,必须实现所有抽象方法。 我希望所有子类都以2个整数作为参数实现一个构造函数。 声明构造函数违反了我的目的,因为我希望在子类中定义构造函数,而我对实现一无所知。而且,我不能将构造函数声明为抽象的。 有没有办法做到这一点 ? 我想要的例子: 可以说我正在定义Matrix类的API。在我的问题中,Matrix无法更改其尺寸。
主要内容:默认拷贝构造函数拷贝和复制是一个意思,对应的英文单词都是 。 对于计算机来说,拷贝是指用一份原有的、已经存在的数据创建出一份新的数据,最终的结果是多了一份相同的数据。例如,将 Word 文档拷贝到U盘去复印店打印,将 D 盘的图片拷贝到桌面以方便浏览,将重要的文件上传到百度网盘以防止丢失等,都是「创建一份新数据」的意思。 在 C++ 中,拷贝并没有脱离它本来的含义,只是将这个含义进行了“特化”,是指用已经存在的对
我有一个受保护的方法(我不希望在超类或子类之外看到此方法)。我想在复制构造函数中使用它,但我不能。法典: 如果我仍然想在不公开 getData() 方法的情况下从超类对象创建子类对象,我该如何克服这个问题? 编辑类在不同的包中!