【问题标题】:How to write Swift generic functions of enum types?如何编写枚举类型的 Swift 泛型函数?
【发布时间】:2014-10-08 08:01:06
【问题描述】:

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

编译失败,并在每个案例行显示消息“Enum case pattern cannot match values of the non-enum type 'Greeting'”。这似乎是因为订阅者协议期望的东西不比 Message 更专业,但我根据 Greeting 进行设置,虽然它实现了 Message,但更专业。 (我说的对吗?)

那么,请问我该怎么做?

【问题讨论】:

    标签: class generics enums swift protocols


    【解决方案1】:

    泛型类型参数T 在Subscriber 的实现中应该仍然是泛型的。 您可以使用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 中,Apple 已经改变了 FooType 与 Foo 的区别(即 Dictionary 现在有 Key和Value 而不是KeyType 和ValueType,而Sequence 现在是SequenceType)。他们对此并非 100% 一致,但在这种情况下,您的答案中的 Message 和 MessageType 似乎是相反的。
    • 你说得对,我用MessageType 使用了克里斯在他的问题中使用的相同类名。
    • 确认!当然。 @Chris,那是给你的……:\
    • 谢谢,@pNre。但除非我有误解,否则您的解决方案不再是通用的。你的意思是说“类型参数 T 应该仍然是通用的”,理论上它是但 Swift 还没有(还没有?)这样做?
    • 我的意思是,当您实例化 SomeObject 时,您不能分配 Message 类型,但您必须绑定到 Greeting。您是否希望SomeObject 的每个实例在receive 中使用不同的类型?在这种情况下,您将无法打开message,因为Hello 和Goodbye 是Greeting 字段。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多