如何在 Scala 中对对象进行模式匹配
Posted
技术标签:
【中文标题】如何在 Scala 中对对象进行模式匹配【英文标题】:How to pattern match objects in Scala 【发布时间】:2021-11-11 15:10:15 【问题描述】:我正在尝试对对象列表使用模式匹配。该方法采用queue: List[ScheduleChangeEvent]
。 ScheduleChangeEvent
是一个 sealed trait
,有 4 个不同的 final case class
。因此,根据列表包含的ScheduleChangeEvent
的类型,我需要做一些不同的事情。
我实现了以下内容:
queue match
case lsc: List[LocationSettingsChange] =>
...
case lwhc: List[LocationWorkHoursChange] =>
...
case tpc: List[TeamParameterChange] =>
...
case mptc: List[MemberPrimaryTeamChange] =>
...
但是,我收到警告 unreachable code [warn] case tpc: List[LocationWorkHoursChange] =>
。而且无论传入队列是什么,它总是转到case lac
。我明白警告是什么,但我不明白为什么会收到警告。
【问题讨论】:
您正在点击类型擦除,您想要做的事情并不容易完成并且通常不安全。您可以对列表的每个元素进行模式匹配。 是的,我也收到了擦除警告。问题是我真的需要整个队列,是什么让它不安全?谢谢回复。 @LuisMiguelMejíaSuárez 虽然我相信 Shapeless 确实提供了该功能,但您无法真正在运行时检查List
是否只有一些子类型,这种方式既简单又安全。无论如何,您可以尝试检查列表中的所有元素是否是您的 ADT 的特定实例,但这会很慢并且在某种程度上不安全,或者甚至更好地为您的队列创建一个包装器 ADT。检查这个:scastie.scala-lang.org/BalmungSan/FUVXpbeuR7eqMxgB1887rw/4
【参考方案1】:
这是因为在运行时你有擦除。这意味着 jvm 没有泛型的类型参数值。 IE。而不是 List[LocationSettingsChange]
或 List[LocationWorkHoursChange]
您在运行时只有 List
。你可以用非空列表做的事情是一种case head :: tail if head.isInstanceOf[LocationSettingsChange]
的内省,或者如果你有一个提取器的话。
通常尽量避免应该这样做的情况,如果你可以通过将模式匹配从列表传递到列表元素来做类似的事情:
list.map
case x: LocationSettingsChange => ???
case x: LocationWorkHoursChange=> ???
case x: TeamParameterChange=> ???
case x: MemberPrimaryTeamChange=> ???
这样做你不会有任何擦除问题,但如果你仍然需要这个,你可以使用类型标签并以运行时性能损失为代价匹配它们,这里描述了更多内容:https://docs.scala-lang.org/overviews/reflection/typetags-manifests.html
【讨论】:
以上是关于如何在 Scala 中对对象进行模式匹配的主要内容,如果未能解决你的问题,请参考以下文章