使用子类在 Swift 中实现 NSCopying
Implementing NSCopying in Swift with subclasses
考虑两个 classes。第一个是 Vehicle
,一个符合 NSCopying
:
的 NSObject
subclass
class Vehicle : NSObject, NSCopying {
var wheels = 4
func copyWithZone(zone: NSZone) -> AnyObject {
let vehicle = self.dynamicType()
vehicle.wheels = self.wheels
return vehicle
}
}
第二个class,Starship
,继承自Vehicle
:
class Starship : Vehicle {
var photonTorpedos = 6
var antiGravity = true
override func copyWithZone(zone: NSZone) -> AnyObject {
let starship = super.copyWithZone(zone) as Starship
starship.photonTorpedos = self.photonTorpedos
starship.antiGravity = self.antiGravity
return starship
}
}
此代码无法编译,因为:
Constructing an object of class type 'Vehicle' with a metatype value must use a 'required' initializer.
所以我继续添加所需的初始化程序:
required override init () {
super.init()
}
现在应用程序编译,Starship
对象正确响应 copy()
。
两个问题:
- 为什么用元类型构造对象需要
required
初始化器? (看起来我写的初始化程序什么也没做。)
- 是不是我写错了什么,或者应该添加到初始化器中?有没有我没有考虑的情况?
您需要一个 required
初始化器,因为 Swift 中所需初始化器的子类实现需要它。
根据 Swift 关于 Required nitializers 的文档:
You must also write the required modifier before every subclass
implementation of a required initializer, to indicate that the
initializer requirement applies to further subclasses in the chain.
简答
您不能在不将 init()
标记为 required
的情况下使用 self.dynamicType()
,因为无法保证 Vehicle
的子类也将实现 init()
.
探索问题
看一下The Swift Programming Language: Initialization,上面提到了如何
subclasses do not inherit their superclass initializers by default
子类将继承其超类的初始化器的情况是:
Assuming that you provide default values for any new properties you
introduce in a subclass, the following two rules apply:
Rule 1
If your subclass doesn’t define any designated initializers, it
automatically inherits all of its superclass designated initializers.
Rule 2
If your subclass provides an implementation of all of its superclass
designated initializers—either by inheriting them as per rule 1, or by
providing a custom implementation as part of its definition—then it
automatically inherits all of the superclass convenience initialisers.
看例子:
class MySuperclass {
let num = 0
// MySuperclass is given `init()` as its default initialiser
// because I gave `num` a default value.
}
class MySubclass : MySuperclass {
let otherNum: Int
init(otherNum: Int) {
self.otherNum = otherNum
}
}
根据上面的信息,由于MySubclass
定义了没有初始值的属性otherNum
,它不会自动从[=20=继承init()
].
现在假设我想将以下方法添加到 MySuperclass
:
func myMethod() {
println(self.dynamicType().num)
}
你会得到你描述的错误,因为不能保证 MySuperclass
的子类会实现 init()
(在这个例子中他们不会)。
要解决此问题,您需要将 init()
标记为 required
,以确保 MySuperclass
的所有子类实现 init()
,因此调用 self.dynamicType()
是一件有效的事情。这与您的问题中的问题相同:Swift 知道 Vehicle
实现 init()
,但是它不知道任何子类将实现 init()
,因此您需要将其 required
。
另一个不适合您的示例的解决方案是将 Vehicle
标记为 final
,这意味着 Vehicle
不能被子类化。然后你就可以使用 self.dynamicType()
;但在这种情况下,您也可以只使用 Vehicle()
。
考虑两个 classes。第一个是 Vehicle
,一个符合 NSCopying
:
NSObject
subclass
class Vehicle : NSObject, NSCopying {
var wheels = 4
func copyWithZone(zone: NSZone) -> AnyObject {
let vehicle = self.dynamicType()
vehicle.wheels = self.wheels
return vehicle
}
}
第二个class,Starship
,继承自Vehicle
:
class Starship : Vehicle {
var photonTorpedos = 6
var antiGravity = true
override func copyWithZone(zone: NSZone) -> AnyObject {
let starship = super.copyWithZone(zone) as Starship
starship.photonTorpedos = self.photonTorpedos
starship.antiGravity = self.antiGravity
return starship
}
}
此代码无法编译,因为:
Constructing an object of class type 'Vehicle' with a metatype value must use a 'required' initializer.
所以我继续添加所需的初始化程序:
required override init () {
super.init()
}
现在应用程序编译,Starship
对象正确响应 copy()
。
两个问题:
- 为什么用元类型构造对象需要
required
初始化器? (看起来我写的初始化程序什么也没做。) - 是不是我写错了什么,或者应该添加到初始化器中?有没有我没有考虑的情况?
您需要一个 required
初始化器,因为 Swift 中所需初始化器的子类实现需要它。
根据 Swift 关于 Required nitializers 的文档:
You must also write the required modifier before every subclass implementation of a required initializer, to indicate that the initializer requirement applies to further subclasses in the chain.
简答
您不能在不将 init()
标记为 required
的情况下使用 self.dynamicType()
,因为无法保证 Vehicle
的子类也将实现 init()
.
探索问题
看一下The Swift Programming Language: Initialization,上面提到了如何
subclasses do not inherit their superclass initializers by default
子类将继承其超类的初始化器的情况是:
Assuming that you provide default values for any new properties you introduce in a subclass, the following two rules apply:
Rule 1
If your subclass doesn’t define any designated initializers, it automatically inherits all of its superclass designated initializers.
Rule 2
If your subclass provides an implementation of all of its superclass designated initializers—either by inheriting them as per rule 1, or by providing a custom implementation as part of its definition—then it automatically inherits all of the superclass convenience initialisers.
看例子:
class MySuperclass {
let num = 0
// MySuperclass is given `init()` as its default initialiser
// because I gave `num` a default value.
}
class MySubclass : MySuperclass {
let otherNum: Int
init(otherNum: Int) {
self.otherNum = otherNum
}
}
根据上面的信息,由于MySubclass
定义了没有初始值的属性otherNum
,它不会自动从[=20=继承init()
].
现在假设我想将以下方法添加到 MySuperclass
:
func myMethod() {
println(self.dynamicType().num)
}
你会得到你描述的错误,因为不能保证 MySuperclass
的子类会实现 init()
(在这个例子中他们不会)。
要解决此问题,您需要将 init()
标记为 required
,以确保 MySuperclass
的所有子类实现 init()
,因此调用 self.dynamicType()
是一件有效的事情。这与您的问题中的问题相同:Swift 知道 Vehicle
实现 init()
,但是它不知道任何子类将实现 init()
,因此您需要将其 required
。
另一个不适合您的示例的解决方案是将 Vehicle
标记为 final
,这意味着 Vehicle
不能被子类化。然后你就可以使用 self.dynamicType()
;但在这种情况下,您也可以只使用 Vehicle()
。