Tim Dean
Tim Dean

Reputation: 8292

Further constraining a generic function from a Swift Protocol

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?

Upvotes: 2

Views: 1584

Answers (2)

matt
matt

Reputation: 535159

One solution is to go the other way - define your protocol's version of the generic as the most restrictive case. This compiles:

protocol P {
    func genericMethod<T where T:P, T:Comparable>(param:T) -> ()
}

class C1 : P {
    func genericMethod<T> (param:T) -> () {} // compiles even though omits Comparable
    func test() {
        genericMethod(C1()) // compiles even though C1 is not a Comparable
    }
}

Upvotes: 0

Daniel T.
Daniel T.

Reputation: 33967

Adding the additional constraint on a generic type should cause it to cease conforming with the protocol because the protocol is supposed to guarantee conformance, and conformance cannot be guaranteed with subtypes that aren't Comparable. If you want all MyProtocol objects to conform to Comparable then you should make it part of the MyProtocol definition.

protocol MyProtocol: Comparable {
    //...
}

I haven't tried this, but it might also work if you make MyBaseClass a Comparable type.

Upvotes: 2

Related Questions