I have a protocol my swift code base I have protocol with an associated type and two methods. Both of the methods define different generic constrains for the associated type of the protocol. And I would like to make the struct conform two the protocol but with two different associated types.
我有一个协议我的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
}
As an extension I make the struct conform the protocol where the TargetType
will be String
in order to pass it to the show method:
作为扩展,我使struct符合TargetType为String的协议,以便将其传递给show方法:
extension MyData : Convertable {
func convert() -> String { return String(self.data) }
}
So far everything works as expected. But now I also like to have the struct to conform to the Convertable
protocol when TargetType
is bound to an Int. Which seems to be impossible?
到目前为止一切都按预期工作。但是现在我也希望在TargetType绑定到Int时使结构符合Convertable协议。哪个似乎不可能?
The first thing I tried was to add a second definition of the convert method to the extension:
我尝试的第一件事是将convert方法的第二个定义添加到扩展名:
extension MyData : Convertable {
func convert() -> String { return String(self.data) }
func convert() -> Int { return data }
}
The compiler now complains that MyData
does no longer conform to the protocol. Second was to split this into two extensions and bind the TargetType explicitly.
编译器现在抱怨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) }
}
This has the effect that the compiler now complains the the TargetType
was redefined.
这会导致编译器现在抱怨重新定义了TargetType。
My last try was to define two protocols that extend the Convertable
protocol and constrain the TargetType
and then implement both of them via extension:
我的最后一次尝试是定义两个扩展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) }
}
Which now makes the compiler happy for the extensions but no longer for the call to show
because it doesn’t know that it can call the function with MyData
.
现在,这使得编译器对扩展感到满意,但不再需要调用show,因为它不知道它可以使用MyData调用该函数。
Is there some thing that I have overseen or is this currently not possible in swift?
是否有一些事情我已经监督过,或者目前在swift中是不可能的?
1 个解决方案
#1
1
I just fund a way to archive this. The trick is to add another associated type in one of the subtypes of the protocol:
我只是资助一种存档方式。诀窍是在协议的一个子类型中添加另一个关联类型:
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 }
}
This also allows to get rid of the second subtype for string.
这也允许摆脱字符串的第二个子类型。
While this passes the compiler it totally crashes at runtime!
虽然这通过了编译器,但它在运行时完全崩溃了!
The compiler always calls the method defined which was defined at the explicit typealias
. In this case:
编译器始终调用在显式类型中定义的已定义方法。在这种情况下:
typealias TargetType = String
Which will result in interpreting the address as a integer and give you totally wrong results. If you define it vice versa it will simply crash because it tries to interpret the integer as a address.
这将导致将地址解释为整数并给出完全错误的结果。如果你反之亦然,那么它就会崩溃,因为它试图将整数解释为一个地址。
#1
1
I just fund a way to archive this. The trick is to add another associated type in one of the subtypes of the protocol:
我只是资助一种存档方式。诀窍是在协议的一个子类型中添加另一个关联类型:
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 }
}
This also allows to get rid of the second subtype for string.
这也允许摆脱字符串的第二个子类型。
While this passes the compiler it totally crashes at runtime!
虽然这通过了编译器,但它在运行时完全崩溃了!
The compiler always calls the method defined which was defined at the explicit typealias
. In this case:
编译器始终调用在显式类型中定义的已定义方法。在这种情况下:
typealias TargetType = String
Which will result in interpreting the address as a integer and give you totally wrong results. If you define it vice versa it will simply crash because it tries to interpret the integer as a address.
这将导致将地址解释为整数并给出完全错误的结果。如果你反之亦然,那么它就会崩溃,因为它试图将整数解释为一个地址。