调用固有树中的协议默认实现



这是一个非常相似的问题:从常规方法调用协议默认实现,但没有一个答案涵盖固有性起作用的情况。答案建议将其转换为协议类型本身可以解决问题,但在这种情况下不会(在操场上复制粘贴(:

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()(最终调用协议的默认实现,因为超类可能也覆盖了协议的默认实施(。所以我真的需要动态调度。

尽管协议支持使用扩展的具体实现,但这违背了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:

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

public protocol MyProtocol {}

最新更新