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