具有相关类型和阴影类型擦除的Swift协议

问题描述 投票:1回答:1

我需要将一个实现具有相关类型的协议的对象传递给一个接受协议的方法。这在Swift中是不可能的(直到最新的Swift 5)所以我使用类型擦除和基于this blog的影子协议。

protocol ShadowA {
    func test(data: Any) -> String
}

extension ShadowA {
    func test(data: Any) -> String {
        return "shadow"
    }
}

protocol A: ShadowA {
    associatedtype AT

    func test(data: AT) -> String
}

class SpecificA: A {
    typealias AT = Int

    func test(data: Int) -> String {
        return "specific"
    }
}

问题是,当我将对象传递给方法时,则调用“影子的默认实现”而不是“通用”实现。你可以检查playground看看发生了什么。

有什么问题或者这个用例在Swift中是不可能的吗?

swift protocols swift-protocols associated-types
1个回答
0
投票

这个动态的Dispatch和直接派遣魔术更多解释一下检查这个swift-method-dispatch

动态分派是选择在运行时调用多态操作(方法或函数)的实现的过程。

protocol extension中实现的任何方法都是Direct dispatched

我会解释更多

因为ShadowAprotocol并且扩展了default implementation所以编译器头脑有这个暗示“Any class can adopt to this protocol without implement this method because it have default implementation

直接派遣

所以在这一行什么编译器从项目知道test(data:Any)和因为item是具有默认实现的协议,所以它指示它调用直接默认实现

return "in method: \(item.test(data: 0))"

func passedIntoMethod(item: ShadowA) -> String {
    return "in method: \(item.test(data: 0))"
}

也在这一行

let a2: ShadowA = SpecificA()   // becuse compiler know only about a2 at this line that it is Protocol so it direct dispatch it  
print(a2.test(data: 0))

动态调度

这里编译器知道a1是具体类型所以它调用在其中实现的test方法。如果没有实现,那么它将调用默认实现

let a1 = SpecificA()
print(a1.test(data: 0))
© www.soinside.com 2019 - 2024. All rights reserved.