我想编写与此类型模式匹配的函数(只是示例代码):
protocol Event {}
enum LightsEvent: Event {
case SwitchOn
case SwitchOff
}
enum CameraEvent: Event {
case Rolling
case Cut
}
struct EventHandler {
let event: Event
func handle(event: LightsEvent) {
// do something with lights
}
func handle(event: CameraEvent) {
// do something with camera
}
}
let handler = EventHandler(event: LightsEvent.SwitchOn)
handler.handle(handler.event) // error: Cannot invoke 'handle' with type ('Event')
我觉得应该编译,但事实并非如此。这迫使我添加一个像这样的开关函数:
func handle(event: Event) {
switch event {
case let e as LightsEvent: handle(e)
case let e as CameraEvent: handle(e)
default: fatalError()
}
}
但是每次我向处理程序添加其他类型的事件时,我都不想为此开关添加另一个案例。有谁知道如何更优雅地解决这个问题?
答案 0 :(得分:1)
向EventHandler
添加泛型将使其有效:
struct EventHandler<T: Event> {
let event: T
func handle(event: LightsEvent) {
print("lights: \(event)");
}
func handle(event: CameraEvent) {
print("camera: \(event)");
}
}
let handler = EventHandler(event: LightsEvent.SwitchOn)
handler.handle(handler.event)
然而,这仍然不够优雅,因为我们在构建EventHandler
时以及调用handle
方法时两次传递相同的事件。
您也无法在EventHandler
中保留对该事件的引用,因为它可能不需要,只需要处理它:
struct EventHandler {
func handle(event: LightsEvent) {
print("lights: \(event)");
}
func handle(event: CameraEvent) {
print("camera: \(event)");
}
}
let handler = EventHandler()
handler.handle(LightsEvent.SwitchOn)
答案 1 :(得分:0)
protocol Event {}
enum Events : Event {
case One, Two
}
struct EventHandler {
let event: Events
func handle<T: Event>(event: T) {
print(event)
}
}
let handler = EventHandler(event: Events.Two)
handler.handle(handler.event) // prints "Two"
但是,如果您只想将协议用作空虚拟类型约束,那么您也可以删除它并只删除枚举
enum Events {
case One, Two
}
struct EventHandler {
let event: Events
func handle(event: Events) {
print(event)
}
}
let handler = EventHandler(event: Events.Two)
handler.handle(handler.event) // prints "Two"