Scala 为什么从案例类提取时映射键类型不起作用?
在以下代码中,映射键可以直接使用,也可以存储在Scala 为什么从案例类提取时映射键类型不起作用?,scala,dictionary,types,Scala,Dictionary,Types,在以下代码中,映射键可以直接使用,也可以存储在val中时使用,但不能存储在案例类中时使用: sealed trait FooKey case object KeyA extends FooKey case object KeyB extends FooKey case class KaseKey(key:FooKey) object Main extends App { val m = Map(KeyA -> "A", KeyB -> "B") val kk = Ka
val
中时使用,但不能存储在案例类中时使用:
sealed trait FooKey
case object KeyA extends FooKey
case object KeyB extends FooKey
case class KaseKey(key:FooKey)
object Main extends App {
val m = Map(KeyA -> "A", KeyB -> "B")
val kk = KaseKey(KeyA)
val kv = KeyA
m(KeyA) // works
m(kv) // works
m(kk.key) // error: found: Main.kk.key.type (with underlying type FooKey)
}
最后一行显示的完整错误为:
错误:(16,8)类型不匹配
找到:Main.kk.key.type(具有基础类型FooKey)
必需:可使用FooKey序列化的产品
这是什么原因?为什么密钥不再被接受,并且一旦存储在案例类中就无法通过类型检查?这是因为以下行推断出密钥的类型:
val m = Map(KeyA -> "A", KeyB -> "B")
如果您查看REPL,它会告诉您它看到了Map[Product with Serializable with FooKey,String]
。这是因为KeyA
和KeyB
的常见超类型就是这样。案例类提供了产品
特性,允许在产品元素上进行迭代,定义等于
和哈希代码
因此,您应该为地图添加注释:
val m = Map[FooKey, String](KeyA -> "A", KeyB -> "B")
或者,您可以定义
sealed trait FooKey extends Product with Serializable
如中所述,这是因为对映射键使用case objects
的结果是m
的类型被推断为FooKey
,而不是可与FooKey序列化的产品
可以通过使用普通的对象
而不是案例对象
来避免这种情况:
sealed trait FooKey
object KeyA extends FooKey
object KeyB extends FooKey
一个可能的缺点是使用了a,这可能不如这里的case对象所提供的合理val m:Map[FooKey,String]=Map(KeyA->“A”,KeyB->“B”)m(kk.key)
似乎有效。还有一种选择,我可以将其中一个键归因于从可能的键类型中删除Product
:val m=Map((KeyA:FooKey>)-“A”,KeyB->“B”)
您使用的是哪个版本的Scala?在Scala 2.11中,case类和case对象都实现了Product
。作为一种特性,FooKey
根据定义是抽象的,不需要实现任何东西。您是正确的。我把它误认为是一个密封类
(它显示了与我的原始示例相同的行为)。简单地说,正确的方法是将键类型显式指定为FooKey