实现具有不同关联类型的协议
implement protocol with different associated type
我有一个协议我的 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
协议。哪个似乎是不可能的?
我尝试的第一件事是将转换方法的第二个定义添加到扩展中:
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
定义的方法。在这种情况下:
typealias TargetType = String
这将导致将地址解释为整数并给您完全错误的结果。如果你反之定义它,它只会崩溃,因为它试图将整数解释为地址。
我有一个协议我的 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
协议。哪个似乎是不可能的?
我尝试的第一件事是将转换方法的第二个定义添加到扩展中:
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
定义的方法。在这种情况下:
typealias TargetType = String
这将导致将地址解释为整数并给您完全错误的结果。如果你反之定义它,它只会崩溃,因为它试图将整数解释为地址。