Reputation: 4895
I am on Swift 5. I have a protocol:
protocol Pipe {
associatedtype T
func await() -> Void
func yield( to: Any, with listener: Selector ) -> Void
}
And I would like to reference an instance of this protocol somewhere in code. That is, I want foo : , or a variable of generic type T implementing Pipe. Per this documentation: https://docs.swift.org/swift-book/ReferenceManual/GenericParametersAndArguments.html
I tried writing:
var imageSource: <Pipe T>
and any permutation of said symbols, ie imageSource: but the syntax is wrong across all cases.
In fact, T conform to two protocols, Renderable and Pipe, so I really want:
var imageSource: <Pipe, Renderable T>
Syntax wise this is gibberish, but semantically it's not an uncommon use case.
__________________ EDIT after two answers have been given __________
I tried simplifying the Pipe
protocol for this post, but now I realize I simplified it too much. In my code base it's
protocol Pipe {
associatedtype T
func await() -> Void
func yield( to: Any, with listener: Selector ) -> Void
func batch() -> [T]
}
That's why there's a T there. But it's not crucial, I can drop the batch() -> [T]
if I am able to write what I want above.
Upvotes: 1
Views: 1697
Reputation: 22385
An associated type is used when you want your protocol to work with a variety of types, think a Container
protocol that might have several methods all dealing with one contained type.
But your protocol is not that, it doesn't need to know any other types to specify the necessary behavior, so get rid of the associated type.
protocol Pipe {
func await() -> Void
func yield( to: Any, with listener: Selector ) -> Void
}
class Foo {
var imageSource: Pipe & Renderable
}
Upvotes: 2
Reputation: 299703
This is called a generalized existential, and is not available in Swift. A protocol with an associated type describes other types; it is not a type itself and cannot be the type of a variable, or put into a collection.
This specific protocol doesn't make a lot of sense, since you don't use T
anywhere. But what you would need to do is pull this into the containing type:
struct Something<Source> where Source: Pipe & Renderable {
var imageSource: Source
}
I suspect you really want to redesign this in a different way, however. This looks like a fairly common misuse of protocols. You probably want Pipe
and Renderer
types that are structs (or even just functions). Without knowing what the calling code looks like, I can't say precisely how you would design it.
If you remove T
(which isn't being used here), then Max's answer will address this issue. Protocols without associated types have an implicit existential type, and so you can treat them somewhat as "normal" types (assigning them to variables or putting them in collections).
Upvotes: 2