使用密封特性作为地图的关键

the*_*met 5 scala traits

我试图从密封特征的实例定义一个地图.在下面的代码中,Scala似乎将键类型推断为Product with Serializable with Day:

object Test extends App {
  sealed trait Day
  case object Sunday extends Day
  case object Monday extends Day
  case object Tuesday extends Day

  val m: Map[Day, Int] = Map(Sunday -> 17, Monday -> 4).withDefaultValue(0)
}
Run Code Online (Sandbox Code Playgroud)

这不编译:

Test.scala:7: error: type mismatch;
 found   : scala.collection.immutable.Map[Product with Serializable with Test.Day,Int]
 required: Map[Test.Day,Int]
Note: Product with Serializable with Test.Day <: Test.Day, but trait Map is invariant in type A.
You may wish to investigate a wildcard type such as `_ <: Test.Day`. (SLS 3.2.10)
  val m: Map[Day, Int] = Map(Sunday -> 17, Monday -> 4).withDefaultValue(0)
Run Code Online (Sandbox Code Playgroud)

我可以在定义中更改键类型m,但这意味着Product with Serializable with Day在许多地方重复.我发现的另一个选择是将特性的定义更改为:

sealed trait Day extends Product with Serializable
Run Code Online (Sandbox Code Playgroud)

由于使用密封特征和案例对象而不是枚举有许多优点,我想知道将它们作为键放在地图中的好方法.

Sar*_*ngh 4

因为Map需要键具有在Product和中定义的属性Serializable,所以 Scala 隐式创建了anonymous class使用 和 扩展您的类Product,并提供了和 的Serializable默认实现。equalshash

object Test extends App {
  trait PS extends Product with Serializable
  sealed trait Day extends PS
  case object Sunday extends Day
  case object Monday extends Day
  case object Tuesday extends Day

  val m: Map[Day, Int] = Map(Sunday -> 17, Monday -> 4).withDefaultValue(0)
}
Run Code Online (Sandbox Code Playgroud)