[英]Why does not Map key type work when extracted from a case class?
在以下代碼中,可以直接使用map鍵,也可以將其存儲在val
,但不能將其存儲在case class
:
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可序列化的產品
這是什么原因呢? 為什么密鑰不再被接受並且一旦存儲在case class
就無法進行類型檢查?
這是因為以下行推斷出了密鑰的類型:
val m = Map(KeyA -> "A", KeyB -> "B")
如果您查看REPL,它將告訴您它看到Map[Product with Serializable with FooKey,String]
。 這是因為KeyA
和KeyB
的常見超類型就是這樣。 案例類為您提供了Product
特質,該特質允許對product元素進行迭代,定義equals
和hashCode
。
因此,您應該注釋地圖:
val m = Map[FooKey, String](KeyA -> "A", KeyB -> "B")
或者,您定義
sealed trait FooKey extends Product with Serializable
正如0__ 的答案所解釋的 ,這是因為將case objects
用作映射鍵的結果是, m
的類型不是FooKey
而是Product with Serializable with FooKey
。
可以通過使用普通objects
而不是case objects
來避免這種case objects
:
sealed trait FooKey
object KeyA extends FooKey
object KeyB extends FooKey
一個可能的缺點是使用了默認的Java對象hashCode ,它可能比case objects
提供的默認值更不合理。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.