Search code examples
swiftgenericsprotocolsgeneric-programming

Swift 5: how to specify a generic type conforming to protocol when declaring a variable


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.


Solution

  • 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
    }