3
votes

In Swift 2, I have a protocol:

protocol Protocol {
    typealias Type
}

When I want to use Protocol without defining what type to use for Type:

var protocol1: Protocol

Then I'm getting the following error:

Protocol 'Protocol' can only be used as a generic constraint because it has Self or associated type requirements

It is clear why this is not going to work.


I have another protocol, which inherits from the first protocol and specifies that the associated type Type should be a String.

protocol AnotherProtocol: Protocol {
    typealias Type = String
}

The same error occurs, when I try to use this protocol:

var protocol2: AnotherProtocol

Protocol 'AnotherProtocol' can only be used as a generic constraint because it has Self or associated type requirements

Why am I getting an error for this, although I have specified the associated type?

Is there another way for the second protocol to specify the associated type of the parent protocol, without having to specify it again in every class that implements the second protocol?

1

1 Answers

2
votes

Your error isn't coming from the declaration or definition of your protocols, it comes from how you're trying to use them. There are two basic ways you can use a protocol: as a pseudo-type, or as a constraint. When you declare a variable like this:

var protocol1: Protocol

You're using the protocol like it's a type: the type of protocol1 is Protocol. This is different from using it as a constraint. Other types conform to the protocol if it's used as a constraint:

struct SomeStruct: Protocol {...

Now, you can use your protocols in either way, but there are some disadvantages to both ways. Firstly, you can't store a heterogenous collection of "protocols as a constraint", whereas you can when you use protocols as a type.

Secondly, if there are requirements on self or associated types, you can no longer use that protocol as a type.

So, here's what I think you're looking for. Your first protocol:

protocol Protocol {
  typealias Type
}

And then the second:

protocol InheritingProtocol {
  typealias Type = String
}

Now, if you want something to conform to the second protocol, it must be used as a constraint. That means that some type conforms to the protocol, and then you can have some instance of that type.

struct SomeType : InheritingProtocol {}

let someInstance = SomeType()