gpt4 book ai didi

swift - 如何在 Swift 子类中实现复制构造函数?

转载 作者:IT王子 更新时间:2023-10-29 05:17:08 28 4
gpt4 key购买 nike

我在 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,你可能会传入父类(super class)中预期的类型,但在子类中已被覆盖以更具限制性:

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 复制?

最佳答案

init(copyFrom: Square)init(copyFrom: Shape) 的重载,而不是覆盖。我的意思是它们是不相关的方法,因为它们接受不同的类型。在 Swift 中这是可以接受的。在 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"}

swift 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
}

}

关于swift - 如何在 Swift 子类中实现复制构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25808972/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com