覆盖协议扩展默认实现

问题描述 投票:0回答:2

考虑以下代码

// 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 中的任何一个,这些都是生成的。我只能玩扩展。有没有办法在不触及前面提到的三个的情况下实现这一目标?

ios swift overriding protocols
2个回答
2
投票

如果将变量声明为协议类型,它将始终采用协议方法的默认实现,因为该方法是在协议的扩展中声明的。

如果不将方法添加到协议声明本身(您已声明这对您来说不可能),访问符合类型的特定实现的唯一方法是将

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"

0
投票

这里接受的答案是不正确的 - 类在默认协议实现上使用自己的实现,即使变量类型是协议类型。这就是多态性始终发挥作用的方式,协议也不例外。最有可能发生的情况是 OP 协议方法签名和类的实现方法签名不匹配。您可能还想验证类实现是否可以从您调用它的位置访问 - 就像它不在另一个模块的某些私有扩展中一样...我可以向您保证该类的具体实现优于协议默认值在这种情况下 - 我现在在我的机器上通过了一个测试来验证这一点。如果您不相信我,请在沙箱中尝试...

© www.soinside.com 2019 - 2024. All rights reserved.