我通过接口描述语言在外部定义并生成了几个Event类。这些类型的定义超出了我的控制范围 - 我只能访问简单生成的案例类:
sealed trait Event
case class EventOpen(msg: String) extends Event
case class EventClose(msg: String) extends Event
鉴于这些事件的列表,我需要将它们折叠成单个值。目的是建立一个折叠函数库,可以根据需要为给定的上下文使用。例如,确定流是打开还是关闭。为了避免折叠函数内部的巨大模式匹配,因为事件列表很长,我希望使用隐式类,根据需要为每个事件添加功能,并根据需要打包导入:< / p>
sealed trait Status
case object Open extends Status
case object Closed extends Status
case object Unknown extends Status
// Do nothing unless a specific EventOp is defined.
implicit class EventNoOp(event: Event) {
def accumulate(status: Status): Status = status
}
implicit class EventOpenOp(event: EventOpen) {
def accumulate(status: Status): Status = Open
}
implicit class EventCloseOp(event: EventClose) {
def accumulate(status: Status): Status = Closed
}
val initial: Status = Unknown
List(EventOpen("yeeha"), EventClose("adios")).foldLeft(initial)((status, event) => event.accumulate(status)) // => Unknown
问题是特定类型的事件在折叠中丢失,因此只调用EventNoOp,导致“未知”而不是“已关闭”。折叠函数内部的明确模式匹配解决了这个问题,但这首先违背了该方法的目的:
val initial: Status = Unknown
List(EventOpen("yeeha"), EventClose("adios")).foldLeft(initial)((status, event) => {
event match {
case e: EventOpen => e.accumulate(status)
case e: EventClose => e.accumulate(status)
}
})
有没有办法避免每个事件的显式模式匹配?
答案 0 :(得分:4)
有没有办法避免每个事件的显式模式匹配?
我认为使用implicits的解决方案实际上导致更多样板文件比使用模式匹配...这对我来说比基于隐式的解决方案更直观:
def accumulateStatus(status: Status, event: Event): Status = event match {
case EventOpen(_) => Open
case EventClose(_) => Closed
case _ => status
}
val initial: Status = Unknown
List(EventOpen("yeeha"), EventClose("adios")).foldLeft(initial)(accumulateStatus)
由于你不能直接修改Event
类,你将会遇到模式匹配(或者使用运行时类型比较/反射做一些更尴尬的事情)。