简体   繁体   中英

Why does not Map key type work when extracted from a case class?

In following code, the map key can be used directly or when stored in a val , but not when stored in a 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)
}

The full error shown for the last line is:

Error:(16, 8) type mismatch;

found : Main.kk.key.type (with underlying type FooKey)

required: Product with Serializable with FooKey

What is the reason for this? Why is the key no longer accepted and fails a type check once stored in a case class ?

This is because of the key's type inferred by the following line:

val m = Map(KeyA -> "A", KeyB -> "B")

If you look at the REPL, it will tell you that it sees Map[Product with Serializable with FooKey,String] . This is because the common super-type of KeyA and KeyB is just that. Case classes give you the Product trait that allows iteration over the product elements, defines equals and hashCode .

So you should annotate your map:

val m = Map[FooKey, String](KeyA -> "A", KeyB -> "B")

Alternatively you define

sealed trait FooKey extends Product with Serializable

As explained in the answer by 0__ , this is because as a result of using case objects for the map keys the type of m is inferred not as FooKey , but as Product with Serializable with FooKey .

One could avoid this by using plain objects instead of case objects :

sealed trait FooKey
object KeyA extends FooKey
object KeyB extends FooKey

One possible drawback is a default Java Object hashCode is used, which may be less reasonable than the one provided by the case objects .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM