微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

swift – 实现具有不同关联类型的协议

我有一个协议我的 swift代码我有协议与相关的类型和两个方法.这两种方法都为协议的相关类型定义了不同的通用约束.我想使结构符合协议,但有两种不同的关联类型.

protocol Convertable {
    associatedtype targettype
    func convert() -> targettype
}

func show<T : Convertable where T.targettype == String>(toShow : T) {
    print(toShow.convert())
}
func add<T : Convertable where T.targettype == Int>(a : T,b : T) -> Int {
    return a.convert() + b.convert()
}

struct MyData {
    var data : Int
}

作为扩展,我使结构符合targettype将为String的协议,以便将其传递给show方法

extension MyData : Convertable {
    func convert() -> String { return String(self.data) }
}

到目前为止一切都按预期工作.但是现在我也希望在targettype绑定到Int时使结构符合Convertable协议.哪个似乎不可能?

我尝试的第一件事是将convert方法的第二个定义添加到扩展名:

extension MyData : Convertable {
    func convert() -> String { return String(self.data) }
    func convert() -> Int { return data }
}

编译器现在抱怨MyData不再符合协议.其次是将其拆分为两个扩展并显式绑定targettype.

extension MyData : Convertable {
    typealias targettype = Int
    func convert() -> Int { return data }
}
extension MyData : Convertable {
    typealias targettype = String
    func convert() -> String { return String(data) }
}

这会产生编译器现在抱怨重新定义targettype效果.

我的最后一次尝试是定义两个扩展Convertable协议并约束targettype的协议,然后通过扩展实现它们:

protocol ConvertableString : Convertable {
    associatedtype targettype = String
}
protocol ConvertableInt : Convertable {
    associatedtype targettype = Int
}

extension MyData : ConvertableInt {
    func convert() -> Int { return self.data }
}
extension MyData : ConvertableString {
    func convert() -> String { return String(self.data) }
}

在这使得编译器对扩展感到满意,但不再需要调用show,因为它不知道它可以使用MyData调用函数.

是否有一些事情我已经监督过或者目前在swift中是不可能的?

解决方法

我只是资助一种存档方式.诀窍是在协议的一个子类型中添加一个关联类型:

protocol ConvertableInt : Convertable {
    associatedtype TResI
    typealias targettype = TResI
}

extension MyData : Convertable {
    typealias targettype = String
    func convert() -> String { return String(self.data) }
}

extension MyData : ConvertableInt {
    typealias TResI = Int
    func convert() -> TResI { return self.data }
}

这也允许摆脱字符串的第二个子类型.

虽然这通过了编译器,但它在运行时完全崩溃了!

编译器始终调用在显式类型中定义的已定义方法.在这种情况下:

typealias targettype = String

这将导致将地址解释为整数并给出完全错误的结果.如果你定义它反之亦然它会崩溃,因为它试图将整数解释为一个地址.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐