Reputation: 480
Given:
protocol MyProtocol {
typealias T
var abc: T { get }
}
And a class that implements MyProtocol:
class XYZ: MyProtocol {
typealias T = SomeObject
var abc: T { /* Implementation */ }
}
How can I define an array of objects conforming to MyProtocol
?
var list = [MyProtocol]()
Gives (together with a ton of SourceKit crashes) the following error:
Protocol 'MyProtocol' can only be used as a generic constraint because it has Self or associated type requirements
Even though the typealias is in fact defined in MyProtocol
.
Is there a way to have a list of object conforming to a protocol AND having a generic constraint?
Upvotes: 8
Views: 1874
Reputation: 72760
The problem is about using the generics counterpart for protocols, type aliases. It sounds weird, but if you define a type alias, you cannot use the protocol as a type, which means you cannot declare a variable of that protocol type, a function parameter, etc. And you cannot use it as the generic object of an array.
As the error say, the only usage you can make of it is as a generic constraint (like in class Test<T:ProtocolWithAlias>
).
To prove that, just remove the typealias from your protocol (note, this is just to prove, it's not a solution):
protocol MyProtocol {
var abc: Int { get }
}
and modify the rest of your sample code accordingly:
class XYZ: MyProtocol {
var abc: Int { return 32 }
}
var list = [MyProtocol]()
You'll notice that it works.
You are probably more interested in how to solve this problem. I can't think of any elegant solution, just the following 2:
T
with AnyObject
(ugly solution!!)but as you may argue, I don't like any of them. The only suggestion I can provide is to rethink of your design and figure out if you can use a different way (i.e. not using typealiased protocol) to achieve the same result.
Upvotes: 3