Reputation: 1136
Is there a way to define a generic function in a protocol and allow the conforming object to define specializations for that protocol? For example:
protocol Generic {
func generic<T>(prop: T, otherProp: String)
}
class Gen: Generic {
func generic<T>(prop: T, otherProp: String) {
print("generic")
}
func generic(prop: String, otherProp: String) {
print(prop)
}
}
Now if I use the class like so:
let inst = Gen()
inst.generic(prop: 1, otherProp: "Go")
inst.generic(prop: "Hello", otherProp: "Stop")
I get the expected result of:
generic
Hello
However if I declare inst
to be of type Generic
:
let inst: Generic = Gen()
inst.generic(prop: 1, otherProp: "Go")
inst.generic(prop: "Hello", otherProp: "Stop")
I get:
generic
generic
So, if I have a property of type Generic
, I am unable to use the specialization of the generic function from the implementor of the protocol. Is this expected behavior? Is there a way to achieve the behavior I am looking for, i.e. to use the specialization of the generic function even when accessed through the protocol's interface? I'd appreciate any insight into this. Thanks everyone.
Upvotes: 2
Views: 515
Reputation: 179
You could add the method signature generic(String, String)
in the protocol and add a default implementation with an extension:
protocol Generic {
func generic<T>(prop: T, otherProp: String)
func generic(prop: String, otherProp: String)
}
extension Generic {
func generic(prop: String, otherProp: String) {
generic(prop: prop as Any, otherProp: otherProp)
}
}
Upvotes: 0
Reputation: 54706
If you declare the protocol requirement to be a generic function, you cannot call a more specialised overloaded version of the same function via the protocol type. However, you can specialise the implementation of the generic function for your adopting class by checking the type of the generic input argument.
class Gen: Generic {
func generic<T>(prop: T, otherProp: String) {
if prop is String {
print(prop)
} else {
print("generic")
}
}
}
let inst: Generic = Gen()
inst.generic(prop: 1, otherProp: "Go")
inst.generic(prop: "Hello", otherProp: "Stop")
Upvotes: 2