如何编写Swift枚举类型的通用函数?

12

使用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")
    }
  }
}

这段代码无法编译,会在每个case行处出现"Enum case pattern cannot match values of the non-enum type 'Greeting'"的错误提示。看起来是因为Subscriber协议期望接收不比Message更特殊的内容,但我使用了Greeting进行设置,虽然Greeting实现了Message,但它更加特殊。(我的理解是否正确?)
那么,请问我应该如何实现我的目标呢?
1个回答

12

Subscriber的实现中,泛型类型参数T仍应该是泛型的。 你可以在protocol Subscriber中使用typealias来实现你所需的功能,并对其强制执行Message超类约束:

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")
        }
    }
}

拥有一个通用的 receive 函数可以防止你对 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)

你的答案完全正确,但我认为在beta 5中,苹果已经改变了应该使用FooTypeFoo的事物类型(即,Dictionary现在具有KeyValue而不是KeyTypeValueType,而Sequence现在是SequenceType)。他们并不完全一致,但在这种情况下,你答案中的MessageMessageType似乎是反过来的。 - Nate Cook
你说得对,我使用了 MessageType,以便使用 Chris 在他的问题中使用的相同类名。 - pNre
谢谢,@pNre。但是除非我误解了,你的解决方案不再是通用的了。你在说“类型参数T仍应该是通用的”时是否意味着理论上它是通用的,但Swift(尚未)这样做? - Chris
我的意思是,当你实例化SomeObject时,你不能分配一个Message类型,而是必须绑定到Greeting。你想让SomeObject的每个实例在receive中使用不同的类型吗?在这种情况下,你将无法切换到message,因为HelloGoodbyeGreeting字段。 - pNre
感谢您的帮助 @pNre。 - Chris
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接