Gilberto T. Gilberto T. - 3 months ago 14
Swift Question

Issue with protocol conformance in Swift using associatedtype

I cannot make classes compliant to protocols which use

associatedtype
. In Playground, I've typed a brief and simple example to show that issue: a producer which produces
ItemType
compliant items and a consumer which which consumes them. It follows:

protocol ItemType { }

protocol Producer: class {
associatedtype T: ItemType
func registerConsumer<C: Consumer where C.T == T>(consumer: C)
}

protocol Consumer: class {
associatedtype T: ItemType
func consume<P: Producer where P.T == T>(producer: P, item: T)
}

struct EmptyItem: ItemType { }

class DummyProducer: Producer {
var consumer: DummyConsumer?

func registerConsumer(consumer: DummyConsumer) {
self.consumer = consumer
}
}

class DummyConsumer: Consumer {
func consume(producer: DummyProducer, item: EmptyItem) {
print("Received \(item) from producer \(producer)")
}
}


Xcode warns me the following errors:

Playground execution failed: MyPlaygroundYeYe.playground:14:7: error: type 'DummyProducer' does not conform to protocol 'Producer'
class DummyProducer: Producer {
^
MyPlaygroundYeYe.playground:3:20: note: protocol requires nested type 'T'
associatedtype T: ItemType
^
MyPlaygroundYeYe.playground:22:7: error: type 'DummyConsumer' does not conform to protocol 'Consumer'
class DummyConsumer: Consumer {
^
MyPlaygroundYeYe.playground:9:10: note: protocol requires function 'consume(_:item:)' with type '<P> (P, item: EmptyItem) -> ()' (aka '<τ_1_0> (τ_1_0, item: EmptyItem) -> ()')
func consume<P: Producer where P.T == T>(producer: P, item: T)
^
MyPlaygroundYeYe.playground:23:10: note: candidate has non-matching type '(DummyProducer, item: EmptyItem) -> ()' [with T = EmptyItem]
func consume(producer: DummyProducer, item: EmptyItem) {
^


Any suggestions about the solution (if exists) of that issue?

Answer

You should define your classes DummyProducer and DummyConsumer like this:

class DummyProducer: Producer {
    typealias T = EmptyItem

    func registerConsumer<C: Consumer where C.T == T>(consumer: C) {

    }
}

class DummyConsumer: Consumer {
    typealias T = EmptyItem

    func consume<P: Producer where P.T == T>(producer: P, item: T) {

    }
}

Since you strictly specified associatedType T to be ItemType in protocol definition, you weren't able to use only EmptyItem in your classes because EmptyItem is not the only structure that can adopt ItemType protocol.