【问题标题】:Why does my superclass call the subclass' method instead of its own in Swift?为什么我的超类在 Swift 中调用子类的方法而不是它自己的方法?
【发布时间】:2016-01-13 09:02:56
【问题描述】:

这是一个示例项目:http://cl.ly/3N2u2i1S441M

我在UITableViewCell 超类中,因为在启动子类时我调用super.init()。在子类和超类的inits 的底部,我调用了一个方法,调用styleCell 对其应用样式。此方法来自它们都遵守的协议,其中一个隐式遵守,因为它是子类并且覆盖了该方法。

在超类“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() 中设置其视图时发生崩溃。

【问题讨论】:

  • 你能贴出代码吗,MCVE?
  • MCVE 是什么意思?我会尽快尝试获取代码。

标签: swift uitableview cocoa-touch inheritance uiview


【解决方案1】:

对此进行了很多思考,我认为最好的说明就是将所有内容放在一个“类”中。

通过覆盖doStyle 函数,您实际上是在替换它。您仍然可以使用super. 访问它,但我们无法拨打super.super class 并使其指向它自己的方法。这也是有道理的,因为超类和子类不是两个对象。它们是一个对象,实际上有一个代码源,其中一个在 super 中,另一个在 sub 中。

所以当doStyle 函数被super init 触发时,它会看到被替换/覆盖的方法。

override 擅长做名字所说的事情,覆盖方法。几乎暗示您不要并排使用 super.method 和覆盖方法。

除此之外,这也是一种不好的做法。为独特的功能使用独特的名称(这就是你所拥有的)。在某种程度上,使用相同的名称/协议是有意义的,因为在每个函数中你都在设置一个样式。但这不是两个都需要样式的独立类。您正在有效地设置基本样式和特定样式。两件不同的事情都需要做。

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

【讨论】:

    猜你喜欢
    • 2014-01-22
    • 2015-04-21
    • 2018-08-22
    • 1970-01-01
    • 2013-12-05
    • 2019-11-15
    • 2020-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多