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.
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:
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?
The first thing I tried was to add a second definition of the convert method to the extension:
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.
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.
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:
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
.
Is there some thing that I have overseen or is this currently not possible in swift?
show
"? This works in my playground:let myInt: Int = myData.convert()
andlet myString: String = myData.convert()
. (Type need to be explicitly specified since there are two candidates. OrmyData.convert() as Int
if return value is not needed.) – Franklin Yu