Conforming to multiple instances of a generic protocol

imr*_*mre 6 protocols associated-types swift

I have a Swift protocol MessageHandler with an associated type, a few different Message types, and also a class X:

protocol MessageHandler { 
    associatedtype Message
    func handle(message: Message)
}

class FooMessage {}
class BarMessage {}

class X {}
Run Code Online (Sandbox Code Playgroud)

Now how do I make X able to handle both FooMessages and BarMessages?

Trying this:

extension X: MessageHandler {
    typealias Message = FooMessage
    func handle(message: FooMessage) {}
}
extension X: MessageHandler {
    typealias Message = BarMessage
    func handle(message: BarMessage) {}
}
Run Code Online (Sandbox Code Playgroud)

simply gives a "redundant conformance" error.

This:

protocol FooMessageHandler: MessageHandler where Message == FooMessage {}
protocol BarMessageHandler: MessageHandler where Message == BarMessage {}

extension X: FooMessageHandler {
    func handle(message: FooMessage) {}
}
extension X: BarMessageHandler {
    func handle(message: BarMessage) {}
}
Run Code Online (Sandbox Code Playgroud)

makes the compiler say that X does not conform to either protocols. However, after removing the function from one of them, I get a more interesting complaint: "'FooMessageHandler' requires the types 'BarMessage' and 'FooMessage' be equivalent".

In C++, X would have two bases: MessageHandler<FooMessage> and MessageHandler<BarMessage>. How do I achieve something like that in Swift?

小智 1

消息类型遵循的协议可以使您提供单一类型作为associatedtype.

然后,您可以在您的内部handle(message:)检查消息的类型并进行相应的处理。

protocol BazMessage {}

class FooMessage: BazMessage {}
class BarMessage: BazMessage {}

extension X: MessageHandler {
    typealias Message = BazMessage
    func handle(message: BazMessage) {}
}
Run Code Online (Sandbox Code Playgroud)