考虑以下代码
// GENERATED PROTOCOL, CANNOT BE MODIFIED
protocol SomeProtocol {
}
// GENERATED CLASS, CANNOT BE MODIFIED
class A {
}
// GENERATED CLASS, CANNOT BE MODIFIED
class B: A, SomeProtocol {
}
// I CAN CHANGE ONLY FROM HERE BELOW
extension SomeProtocol {
func someMethod() {
print("protocol implementation")
}
}
extension B {
func someMethod() {
print("class implementation")
}
}
let some: SomeProtocol = B()
some.someMethod() //this prints "protocol implementation"
我想要 some.someMethod() 打印“类实现”。我知道有很多方法可以实现这一点,一种是在 SomeProtocol 中添加 someMethod,但不幸的是,我无法更改 SomeProtocol、A 或 B 中的任何一个,这些都是生成的。我只能玩扩展。有没有办法在不触及前面提到的三个的情况下实现这一目标?
如果将变量声明为协议类型,它将始终采用协议方法的默认实现,因为该方法是在协议的扩展中声明的。
如果不将方法添加到协议声明本身(您已声明这对您来说不可能),访问符合类型的特定实现的唯一方法是将
some
向下转换为 B
或将其存储为首先B
。
let some: SomeProtocol = B()
some.someMethod() //this prints "protocol implementation"
(some as? B)?.someMethod() // this prints "class implementation"
let someB = B()
someB.someMethod() // this prints "class implementation"
这里接受的答案是不正确的 - 类在默认协议实现上使用自己的实现,即使变量类型是协议类型。这就是多态性始终发挥作用的方式,协议也不例外。最有可能发生的情况是 OP 协议方法签名和类的实现方法签名不匹配。您可能还想验证类实现是否可以从您调用它的位置访问 - 就像它不在另一个模块的某些私有扩展中一样...我可以向您保证该类的具体实现优于协议默认值在这种情况下 - 我现在在我的机器上通过了一个测试来验证这一点。如果您不相信我,请在沙箱中尝试...