为什么我的超类称为子类'方法而不是自己在Swift中?

时间:2015-10-15 03:42:05

标签: swift uitableview cocoa-touch inheritance uiview

以下是一个示例项目: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()中设置其视图时,这会导致运行时错误。

1 个答案:

答案 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()
    }
}

即使同时调用initsuper.init,也没有冲突,因为子类不会同时调用它自己的init而它是超级init