继承树中的呼叫协议默认实现

时间:2018-11-07 19:18:14

标签: swift protocols

这是一个非常相似的问题:Calling protocol default implementation from regular method,但是当继承发挥作用时,所有答案都无法解决。答案建议将其强制转换为协议类型本身即可解决,但在这种情况下不可行(在操场上复制粘贴):

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的默认实现?

编辑:我的用例如下: 我有一个被类继承的协议,该协议被大量子类化。该协议有多个默认方法,可以互相调用。一些子类需要重写方法,执行操作并调用super.method()(以最终调用协议的默认实现,因为超类也可能已重写协议的默认实现)。所以我真的需要动态调度。

1 个答案:

答案 0 :(得分:1)

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

  

协议定义了方法,属性和其他方法的蓝图   适合特定任务或功能的需求。

,在您完全确定这不是overriden之前,应尽可能避免。

解决方案1:

如果您遇到了上述情况,那么我建议您介绍一个中介class,除了遵循protocol之外什么都不做,然后从{{1}那里继承subClasses }。

class

现在创建对象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()

解决方案2:

如其他question所述,请从Hi from 2 Hi, I am protocol Cheese from protocol 中删除sayCheese方法,以便您的协议声明为空,但protocol将保留在sayCheese中它将中断对extension的递归调用,从而使您的应用不会冻结。

sayCheese