Home > Enterprise >  Unable to create sender/receiver protocols
Unable to create sender/receiver protocols

Time:12-26

I have 2 protocols like this:

protocol Receiver {
    associatedtype Input
    
    func send(_ input: Input)
}
protocol Sender {
    associatedtype Output
    
    init<T: Receiver>(_ receiver: T) where T.Input == Output
}

To implement Sender, I first do this:

class TestSender: Sender {
    typealias Output = String
    
    required init<T: Receiver>(_ receiver: T) where T.Input == Output {
        
    }
}

However I need to store receiver from init as a class property. Since Receiver has associated type requirements, I have to add a generic type constraint to the entire TestSender class, like this:

class TestSender<T: Receiver>: Sender where T.Input == String

I can then declare a property in TestSender like this:

private let receiver: T

But in the initializer, I can't assign receiver.

required init<T: Receiver>(_ receiver: T) where T.Input == Output {
    self.receiver = receiver // Cannot assign value of type 'T' to type 'T'
}

I tried changing the init method as follows:

init(_ receiver: T) {
    self.receiver = receiver
}

But now, the Swift compiler says I'm not conforming to the protocol correctly. What is the correct way to do something like this?

CodePudding user response:

Solution

You can make the Receiver have an associatedtype on the Sender protocol, so that a Sender is generic over its Receiver.

Code:

protocol Sender {
    associatedtype InputReceiver: Receiver
    associatedtype Output = InputReceiver.Input

    init(_ receiver: InputReceiver)
}
class TestSender<T: Receiver>: Sender {
    typealias Output = String

    private let receiver: T

    required init(_ receiver: T) {
        self.receiver = receiver
    }
}

Why didn't the original code work?

With your latest code, you should see the following error:

Type 'TestSender' does not conform to protocol 'Sender'

This indicates that some requirement is not being satisfied. If you click the fix-it, it shows there is a problem with the initializer. If you click the fix-it again, you get back to the problem of:

Cannot assign value of type 'T' to type 'T'

This is because you have a generic T on TestSender and also a generic T on the initializer. These are different types.

However, ignoring this, the root of the problem is that: in your Sender protocol, you only have a generic on the initializer, where as in your TestSender class you are trying to create a generic over the class itself.

To make a protocol 'generic', you give it an associatedtype. And since the Receiver is the thing to make generic, that was used to create an associatedtype.

Because we have the Receiver generic, we can also get the Output type in Sender as well.

I hope that made sense, ask if you have any questions (it's quite hard to explain!)

  • Related