以下是一个示例项目:http://cl.ly/3N2u2i1S441M
我在UITableViewCell
超类中,因为在启动子类时我调用super.init()
。在子类和超类的init
的底部,我调用一个方法,调用styleCell
来应用样式。这个方法来自他们都遵循的协议,其中一个隐式符合,因为它是子类,它覆盖了方法。
在超级课程结束时#39; init
,调用该样式方法,但它调用子类' styleCell
方法,而不是它自己的方法。
为什么会发生这种情况?
这是Swift的错误吗?除了上面的项目之外,我还附上了一些代码以显示问题:
超类表格单元格:
class SuperTableViewCell: UITableViewCell, Style {
var mysuperview: UIView!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
mysuperview = UIView()
doStyle()
}
required init?(coder aDecoder: NSCoder) {
fatalError("Must be created in code.")
}
func doStyle() {
print("super class")
}
}
子类表格单元格:
class SubTableViewCell: SuperTableViewCell {
var mysubview: UIView!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
mysubview = UIView()
doStyle()
}
required init?(coder aDecoder: NSCoder) {
fatalError("Must be created in code.")
}
override func doStyle() {
super.doStyle()
mysubview!.backgroundColor = UIColor.greenColor()
}
}
样式类和协议:
class StyleManager: NSObject {
}
protocol Style {
func doStyle()
}
当子类单元尝试在doStyle()
中设置其视图时,这会导致运行时错误。
答案 0 :(得分:2)
对此有很多想法,我认为最好的例子就是把它全部放在一个“班级”中。
通过覆盖doStyle
函数,您实际上正在替换它。您仍然可以使用super.
访问它,但我们无法拨打super.
来自super class
,并指出它自己的方法。这也很有意义,因为super和subclasses不是两个对象。它们是一个实际上有一个代码源的对象,其中一个在super中,另一个在sub中。
因此当doStyle
函数被super init
触发时,它会看到被替换/重写的方法。
override
很擅长做名字所说的,覆盖方法。几乎暗示你不要并排使用super.method和override方法。
除此之外,这也只是不好的做法。为唯一功能使用唯一名称(这就是您所拥有的)。在某种程度上,使用相同的名称/协议是有意义的,因为在每个函数中您都在设置样式。但这些不是两个都需要风格的单独类。您正在有效地设置基本样式和特定样式。两个不同的事情都需要做。
class SuperSubIllustation {
// super and sub class as one for illustation
init() {
subInit()
}
func superInit() {
print("super init")
overrideDoStyle() // this calls the sub style because it's own method is overridden
}
func subInit() { // the sub init, this overrides the superInit
print("sub init")
superInit() // the super.init()
overrideDoStyle() // the sub style
}
func doStyle() {
print("super style")
}
func overrideDoStyle() {
print("sub style")
doStyle() // the super.doStyle
}
}
旁注:
在进行子类化时,您经常会创建越来越具体的代码。例如,一系列UIButton类。
class RoundedCornersButton : UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
self.layer.cornerRadius = 5
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.layer.cornerRadius = 5
}
}
class GreenButton : RoundedCornersButton {
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.greenColor()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.backgroundColor = UIColor.greenColor()
}
}
class RedButton : RoundedCornersButton {
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.redColor()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.backgroundColor = UIColor.redColor()
}
}
即使同时调用init
和super.init
,也没有冲突,因为子类不会同时调用它自己的init
而它是超级init
。