I have a Swift protocol defined like this:
protocol MyProtocol {
func genericMethod<T:MyProtocol>(param:T) -> ()
}
I can implement the generic method in a base class like this:
class MyBaseClass : MyProtocol {
func genericMethod<T where T:MyProtocol>(param:T) -> () {
println("Performing generic method for type \(T.self)")
}
}
class MySubClass : MyBaseClass {
...
}
So far, so good. I can implement this method and it compiles and runs just fine.
Now, I want to do something similar but in my base class I want to further constrain the type of the generic method by requiring it to conform with a protocol such as Comparable
. I try this:
class MyBaseClass : MyProtocol {
func genericMethod<T where T:MyProtocol, T:Comparable>(param:T) -> () {
println("Performing generic method for type \(T.self)")
}
}
Once I add this additional constraint on type T
, the class MyClass
will not compile because it does not conform to the protocol anymore.
It seems like adding an additional constraint on a generic type should not cause it to cease conforming with a protocol. What am I missing? It seems to me that the protocol is saying that genericMethod
must be passed a parameter of a type that conforms with MyProtocol
. When I go to implement this in MyBaseClass
- just one possible implementation of MyProtocol
- that I should be able to restrict that implementation further by saying that the parameter myst conform with Comparable
in addition to MyProtocol
Is there a way to refine a generic type in a base implementation like I'm trying to do here?
genericMethod
with the parameter being his own type. ButT:MyBaseClass, T:Comparable
is not MyBaseClass's own type, since MyBaseClass does not adopt Comparable. So, as the compiler says, you've violated the contract laid out by the protocol. – mattSelf
reference in the protocol was just one way to demonstrate the problem. I get the same problem if I use one protocol and then another. I will update the question to make it more clear why I am surprised at this behavior – Tim Deanfunc genericMethod<T:MyProtocol>(param:T) -> ()
is not the same asfunc genericMethod<T where T:MyProtocol, T:Comparable>(param:T) -> ()
. You are saying in a kind of mental justificatory footnote "one is a more restricted version of the other", but that doesn't matter to the compiler; the point is that one is not the other. – mattfunc genericMethod<T> (param:T) -> ()
andfunc genericMethod<T where T:Comparable>(param:T) -> ()
. They are not a match either, and it's clearer why, I think. To put it another way, you seem to think that one generic is a kind of "subclass" or "subset" of the other. But that's not how these generic signatures work. It's a match or it isn't. – matt