考虑两个班级。第一个是Vehicle
,NSObject
子类符合NSCopying
:
class Vehicle : NSObject, NSCopying {
var wheels = 4
func copyWithZone(zone: NSZone) -> AnyObject {
let vehicle = self.dynamicType()
vehicle.wheels = self.wheels
return vehicle
}
}
第二课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
}
}
此代码无法编译,因为:
使用元类型值构造类型为“Vehicle”的对象必须使用“必需”初始值设定项。
所以我继续添加一个必需的初始化程序:
required override init () {
super.init()
}
现在应用程序已编译,Starship
个对象正确回复copy()
。
两个问题:
required
初始值设定项? (看来我写的初始化程序什么也没做。)答案 0 :(得分:12)
如果没有将self.dynamicType()
标记为init()
,则无法使用required
,因为无法保证Vehicle
的子类也会实现init()
。
看看 The Swift Programming Language: Initialization ,它提到了如何
子类默认不继承其超类初始值设定项
子类将继承其超类'初始化者的情况是:
假设您为任何新属性提供默认值 在子类中引入,适用以下两个规则:
规则1
如果你的子类没有定义任何指定的初始化器,那么它 自动继承其所有超类指定的初始化器。
规则2
如果您的子类提供了其所有超类的实现 指定的初始化程序 - 通过按照规则1继承它们,或者通过 提供自定义实现作为其定义的一部分 - 然后它 自动继承所有超类便利初始化器。
看看这个例子:
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
而没有初始值,因此它不会自动从init()
继承MySuperclass
。
现在假设我想将以下方法添加到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()
。
答案 1 :(得分:0)
你需要一个required
初始化器,因为Swift中所需初始化器的子类实现需要它。
Required nitializers上的每个Swift文档:
您还必须在每个子类之前编写必需的修饰符 执行一个必需的初始化程序,以表示该 初始化程序要求适用于链中的其他子类。