1

我正在尝试定义一个以参数化类为键的映射。但是当我尝试添加它时,我得到一个编译器错误:

trait MyTrait[T <: MyTrait[T]]

case class A(i: Int) extends MyTrait[A]
case class B(str: String) extends MyTrait[B]

var map = Map[Class[_ <: MyTrait[_]], Int]()

def update[T <: MyTrait[T]](n: Int) = {
    map += classOf[T] -> n  // Won't compile
}

我收到以下编译器错误:

  Expression does not convert to assignment because:  
    class type required but T found  
    expansion: map = map.+(classOf[T].<$minus$greater: error>(n))  
        map += classOf[T] -> n  

将我的课程提取为密钥的正确方法是什么?如果我使用具体的类,它编译得很好,例如:

    map += classOf[A] -> n
4

1 回答 1

2

您应该添加上下文绑定ClassTag并替换classOf[T]classTag[T].runtimeClass.

classOf[T]适用于实际类(现在已知是类,例如classOf[Int]classOf[String])。对于类型参数(调用方法时将成为类类型),您需要类标记。

def update[T <: MyTrait[T]: ClassTag](n: Int) = {
  val clazz = classTag[T].runtimeClass.asInstanceOf[Class[T]]
  map += clazz -> n
}

println(map) //HashMap()
update[A](1) 
println(map) //HashMap(class A -> 1)
update[B](2)
println(map) //HashMap(class A -> 1, class B -> 2)

https://docs.scala-lang.org/overviews/reflection/typetags-manifests.html

于 2020-09-30T09:45:36.467 回答