Ale*_*lav 23 cocoa ios sprite-kit swift
作为一个学习练习,我试图实现一个子类,SKShapeNode它提供了一个新的便利初始化器,它接受一个数字并构造一个ShapeNode,它是一个数字宽度和高度的正方形.
根据Swift Book:
规则1
如果您的子类没有定义任何指定的初始值设定项,它会自动继承其所有超类指定的初始值设定项.
规则2
如果您的子类提供了所有超类指定初始化程序的实现 - 通过按照规则1继承它们,或者通过提供自定义实现作为其定义的一部分 - 那么它会自动继承所有超类便利初始化程序.
但是,以下类不起作用:
class MyShapeNode : SKShapeNode {
convenience init(squareOfSize value: CGFloat) {
self.init(rectOfSize: CGSizeMake(value, value))
}
}
Run Code Online (Sandbox Code Playgroud)
相反,我得到:
Playground execution failed: error: <REPL>:34:9: error: use of 'self' in delegating initializer before self.init is called
self.init(rectOfSize: CGSizeMake(value, value))
^
<REPL>:34:14: error: use of 'self' in delegating initializer before self.init is called
self.init(rectOfSize: CGSizeMake(value, value))
^
<REPL>:35:5: error: self.init isn't called on all paths in delegating initializer
}
Run Code Online (Sandbox Code Playgroud)
我的理解是MyShapeNode应该继承所有SKShapeNode的便利初始化器,因为我没有实现任何我自己的指定初始化器,并且因为我的便利初始化器是调用init(rectOfSize),另一个方便初始化器,这应该工作.我究竟做错了什么?
mat*_*att 25
这里有两个问题:
SKShapeNode只有一个指定的初始化程序:init().这意味着我们无法在不调用的情况下退出初始化程序init().
SKShapeNode有一个path声明为的属性CGPath!.这意味着我们不想在不以某种方式初始化的情况下退出初始化程序path.
这两件事的结合是问题的根源.简而言之,SKShapeNode编写错误.它有一个path必须初始化的属性; 因此它应该有一个指定的初始化器来设置path.但它没有(它的所有path初始化器都是便利初始化器).这就是错误.换句话说,问题的根源在于,方便与否,shapeNodeWith...方法根本不是真正的初始化器.
但是,您可以执行您想要执行的操作 - 编写便捷初始化程序而不必强制编写任何其他初始化程序 - 通过按顺序满足这两个要求,即通过这样写:
class MyShapeNode : SKShapeNode {
convenience init(squareOfSize value: CGFloat) {
self.init()
self.init(rectOfSize: CGSizeMake(value, value))
}
}
Run Code Online (Sandbox Code Playgroud)
它看起来是非法的,但事实并非如此.一旦我们调用self.init(),我们就满足了第一个要求,我们现在可以自由地引用self(我们不再在调用self.init之前在委托初始化程序时使用'self')并满足第二个要求需求.
Cez*_*zar 15
我对Initializer继承的理解与你的相同,我认为我们都与本书所述的内容完全一致.我认为这不是解释问题或对所述规则的误解.那就是说,我认为你做错了什么.
我在Playground测试了以下内容,它按预期工作:
class RectShape: NSObject {
var size = CGSize(width: 0, height: 0)
convenience init(rectOfSize size: CGSize) {
self.init()
self.size = size
}
}
class SquareShape: RectShape {
convenience init(squareOfSize size: CGFloat) {
self.init(rectOfSize: CGSize(width: size, height: size))
}
}
Run Code Online (Sandbox Code Playgroud)
RectShape继承自NSObject并且没有定义任何指定的初始化程序.因此,根据规则1,它继承了所有NSObject的指定初始值设定项.在执行intance的设置之前,我在实现中提供的便利初始化程序正确地委托给指定的初始化程序.
SquareShape继承自RectShape,不提供指定的初始化程序,并且,根据规则1,继承所有SquareShape指定的初始化程序.根据规则2,它还继承了在中定义的便利初始化程序RectShape.最后,SquareShape正确定义的便捷初始化程序将委托给继承的便利初始化程序,后者又委托给继承的指定初始化程序.
所以,鉴于你没有做错任何事情以及我的例子按预期工作,我推断以下假设:
由于SKShapeNode是用Objective-C编写的,因此该语言不强制规定"每个便利初始化器必须从同一个类调用另一个初始化器"的规则.因此,也许便捷初始化SKShapeNode器实际上不会调用指定的初始化器.因此,即使子类MyShapeNode按预期继承了方便初始值设定项,它们也不能正确地委托给继承的指定初始值设定项.
但是,这只是一个假设.我所能确认的是,这些机制在我自己创建的两个类中按预期工作.
基于Matt的答案,我们必须包括一个附加函数,否则编译器会抱怨调用不带参数的初始化程序。
这是子类SKShapeNode的工作方式:
class CircleNode : SKShapeNode {
override init() {
super.init()
}
convenience init(width: CGFloat, point: CGPoint) {
self.init()
self.init(circleOfRadius: width/2)
// Do stuff
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15781 次 |
| 最近记录: |