继承树中的调用协议默认实现

Call protocol default implementation in inherence tree

这是一个非常相似的问题:,但是 none 的答案涵盖了 继承发挥作用 的情况。答案建议将其转换为协议类型本身将解决它,但在这种情况下不会(在操场上复制粘贴):

public protocol MyProtocol {
    func sayCheese()
}

public extension MyProtocol {
    func sayHi() {
        print("Hi, I am protocol")
        sayCheese()
    }

    func sayCheese() {
        print("Cheese from protocol")
    }
}

public class MyFirstClass: MyProtocol {
    public func sayCheese() {
        print("Cheese from 1")

        (self as MyProtocol).sayCheese()
    }
}

public class MySecondClass: MyFirstClass {
    override init() {
        super.init()

        sayHi()
    }

    public func sayHi() {
        print("Hi from 2")
        super.sayHi()
    }

    public override func sayCheese() {
        print("Said cheese from 2")
        super.sayCheese()
    }
}

MySecondClass()

它打印以下内容:

...
Said cheese from 2
Cheese from 1
Said cheese from 2
Cheese from 1
...

MyFirstClass 的实例中,如何调用方法 sayCheese 的 MyProtocol 的默认实现?

编辑:我的用例如下: 我有一个被 class 采纳的协议,它经常被 subclass 编辑。该协议有多个默认方法,可以相互调用。一些 subclasses 需要覆盖方法,做一些事情,并调用 super.method() (最终调用协议的默认实现,因为 superclass 可能已经覆盖了协议默认实现也是如此)。所以我真的需要动态调度。

尽管协议支持使用扩展的具体实现,但这违背了 protocol

的概念

A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality.

在您真正确定这不会是 overriden.

之前,应尽可能避免它

解决方案一:

如果您遇到过上述情况,那么我建议引入一个中介 class,它除了符合 protocol 之外什么都不做,然后从 subClasses 继承 subClasses 15=]。

public class Intermediary: MyProtocol {}

public class MyFirstClass: Intermediary {
    public func sayCheese() {
        print("Cheese from 1")

        super.sayCheese()
    }
}

public class MySecondClass: MyFirstClass {
    override init() {
        super.init()

        sayHi()
    }

    public func sayHi() {
        print("Hi from 2")
        super.sayHi()
    }

    public override func sayCheese() {
        print("Said cheese from 2")
        super.sayCheese()
    }
}

现在创建对象 MySecondClass() 将打印以下输出,

Hi from 2
Hi, I am protocol
Cheese from protocol

方案二:

如另一个 中所述,从 protocol 中删除 sayCheese 方法,这样您的协议声明将为空,但 sayCheese 将保留在 extension 并且它会中断对 sayCheese 的递归调用,从而使您的应用不会冻结。

public protocol MyProtocol {}