Using Swift, I want to write a protocol that specifies that implementing classes must have a function that takes an enum (which adheres to a given protocol), where that enum type is specified generically. I've tried this:
protocol Message {}
protocol Subscriber {
func receive<T where T:Message>(message:T)
}
enum Greeting : Message {
case Hello, Goodbye
}
class SomeObject : Subscriber {
func receive<Greeting>(message: Greeting) {
switch message {
case .Hello:
println("Hello")
case .Goodbye:
println("Goodbye")
}
}
}
This fails to compile with the message "Enum case pattern cannot match values of the non-enum type 'Greeting'" at each of the case lines. This would appear to be because the Subscriber protocol expects something that is no more specialized than Message, but I set things up in terms of Greeting, which though it implements Message, is more specialized. (Am I right?)
So, how do I do what I'm attempting to do, please?
The generic type parameter T
should still be generic in the implementation of Subscriber
.
You can do what you ask using a typealias
in protocol Subscriber
and enforce the Message
superclass constraint on it:
protocol Message {}
protocol Subscriber {
typealias MessageType: Message
func receive (message: MessageType)
}
enum Greeting : Message {
case Hello, Goodbye
}
class SomeObject : Subscriber {
typealias MessageType = Greeting
func receive (message: MessageType) {
switch message {
case .Hello:
println("Hello")
case .Goodbye:
println("Goodbye")
}
}
}
Having a generic receive
prevents you from switching on the enum
fields:
protocol Message {}
protocol Subscriber {
func receive <T: Message> (message: T)
}
enum Greeting : Message {
case Hello, Goodbye
}
class SomeObject : Subscriber {
func receive <T: Message> (message: T) {
}
}
let obj = SomeObject()
obj.receive(Greeting.Hello)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With