如何编写枚举类型的快速泛型函数?

时间:2022-11-25 16:53:14

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:

使用Swift,我想编写一个协议,它指定实现类必须具有一个具有枚举(它遵循给定的协议)的函数,其中枚举类型是通用的。我已经试过这个:

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?)

这不能用“Enum case模式不能匹配非枚举类型的‘问候’的值”来进行编译。这似乎是因为订阅方协议期望的是不比消息更专门化的东西,但是我将事情设置为问候语,尽管它实现了消息,但它更专门化。(对吗?)

So, how do I do what I'm attempting to do, please?

那么,我该怎么做呢?

1 个解决方案

#1


9  

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:

泛型类型参数T在订阅服务器的实现中仍然应该是泛型的。您可以在协议订阅器中使用typealias,并对其强制执行消息超类约束:

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:

有一个泛型接收可以防止您切换到enum字段:

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)

#1


9  

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:

泛型类型参数T在订阅服务器的实现中仍然应该是泛型的。您可以在协议订阅器中使用typealias,并对其强制执行消息超类约束:

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:

有一个泛型接收可以防止您切换到enum字段:

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)