【问题标题】:Call protocol default implementation in inherence tree在继承树中调用协议默认实现
【发布时间】:2018-11-07 19:18:13
【问题描述】:

这是一个非常相似的问题: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()(最终调用协议的默认实现,因为超类也可能已经覆盖了协议的默认实现)。所以我真的需要动态调度。

【问题讨论】:

  • 您需要从协议中删除 sayCheese() 要求,以获得您链接的问题的答案所依赖的静态调度。
  • @dan 查看我的编辑

标签: swift protocols


【解决方案1】:

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

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

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

解决方案 1:

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

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

解决方案 2:

正如另一个question 中提到的,从protocol 中删除sayCheese 方法,这样您的协议声明将为空,但sayCheese 将保留在extension 中,并且它将中断对@987654335 的递归调用@ 允许您的应用不冻结。

public protocol MyProtocol {}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-12
    • 1970-01-01
    • 1970-01-01
    • 2021-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多