当前位置: 首页 > 知识库问答 >
问题:

为什么我的超类在Swift中调用子类的方法而不是它自己的方法?

越朗
2023-03-14

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

我在一个UITableViewCell超类中,因为当子类被初始化时,我调用super。init()。在子类和超类的init的底部,我调用了一个方法,调用styleCell,对其应用样式。该方法来自于它们都符合的协议,其中一个隐式符合,因为它是子类,并且覆盖了该方法。

在超类'init的末尾,调用该样式方法,但它调用子类'styleCell方法,而不是它自己的方法。

这究竟是为什么?

这是斯威夫特的臭虫吗?除了上面的项目之外,我还附上了一些代码来说明这个问题:

超类表格单元格:

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个答案

呼延光明
2023-03-14

想了很多,我认为最好的例子就是把它放在一个“类”中。

通过重写doStyle函数,可以有效地替换它。您仍然可以使用super访问它 中进行编码,并使其指向自己的方法。这也是有意义的,因为超类和子类不是两个对象。它们是一个对象,实际上有一个代码源,其中一个在super中,另一个在sub中。

因此,当doStyle函数被超级init触发时,它会看到替换/覆盖的方法。

override擅长做名字所说的事情,覆盖方法。这几乎意味着你不使用super。方法和重写方法并排。

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

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和它的super的init。

 类似资料:
  • 问题内容: 让我们看一下这段代码: 我希望这能打印出“孩子”,但结果是“父母”。为什么Java会改为调用父类,我该怎么做才能使其在子类中调用方法? 问题答案: 不会覆盖,因为它没有相同的形式参数。一个拿走,另一个拿走。因此,运行时的多态不会被应用,并且不会导致子类方法的执行。根据Java语言规范: 如果满足以下所有条件,则在类C中声明或由类C继承的实例方法从类C中 重写 另一个在类A中声明的方法:

  • 我在调用覆盖方法的子类方法时遇到了问题,所以我创建了一个小应用程序来测试它。当超类调用其子类覆盖的方法时,仍然调用超类的方法版本,而不是子类的版本,后者覆盖了超类的方法,应该是被调用的方法。 预期输出:

  • 我有一个基类,它定义了类方法,用于返回用于构建服务url的各种信息。基类还定义了一个用于构建该url的实例方法。我希望基类有这个方法的默认实现,这样当我需要url不同时,我只需要在子类中重写它。我如何让这个基方法调用重写的类方法来使用子类中的类方法构建url?下面是我现在的代码,但它不起作用: 基类方法: op ationId、operationVersion和方法类型是在子类中实现的类方法,但是

  • 我通过在public static void main()方法中实现接口I创建了匿名类。因此,Java8对于抽象方法test()的实现是从C类的imple()方法中提供的。 因此,在public static void main()方法printing_interface.getclass(),我得到了 但最终它打印的是package_path.C(告诉我C是类名)。这怎么可能?不应该再次打印pa

  • 问题内容: 这是我的情况: 逻辑很简单。“ SomeBaseClass”是我无法修改的第三方工具。我想限制其功能,并且不想允许foo(String strs [])。 问题是在SomeBaseClass内部foo(Sting str)内部调用foo(String strs [])。因此,当我调用MyClass的foo(String str)时,出现运行时异常。我该如何告诉SomeBaseClass

  • 问题内容: 我有一个父类A,及其子B。两者都具有带有diff类型参数的方法。 A级 B级 运行此命令时,将获得“ Base impl:override”作为输出! 指向的对象,而他经过的说法是,所以不应该调用它的方法是什么? 问题答案: 当您使用类型A的引用时,您只会看到为类A定义的方法。由于B中不会覆盖B(因为它具有不同的签名),因此不会调用它。 如果要使用类型B的引用,则两种方法都将可用,并且