Scala:参数类型注释将ClassTag重置为Option并破坏类型匹配

时间:2019-06-27 10:02:28

标签: scala jvm type-erasure classtag

我有一个带有类型参数的特征。在此特征内,我想定义一个检查对象是否与type参数匹配的方法。到目前为止,这是可行的,因为我希望它能工作:

import scala.reflect.ClassTag
trait MyTrait[A <: AnyVal]{
    def hasType(x: AnyVal)(implicit tag: ClassTag[A]) = x match {
        case _: A => true
        case _    => false
    }
}

object MyObject extends MyTrait[Int]

println(MyObject.hasType(5))   // returns true
println(MyObject.hasType(5.0)) // returns false

MyTrait-对象是类的参数时,就会发生问题,例如:

class WrappingClass(myObjects: Seq[MyTrait[_]]) {
    def hasType(x: AnyVal) = {
        myObjects.foreach(
            mo => println(mo.hasType(x))
        )
    }
}

object AnotherObject extends MyTrait[Double]
val wrappingObject = new WrappingClass(Seq(MyObject, AnotherObject))
wrappingObject.hasType(5)   // prints only "true"
wrappingObject.hasType(5.0) // prints only "true"

因此,参数的类型注释Seq[MyTrait[_]]使我的ClassTag变成了通用对象,并破坏了类型匹配。我真的想避免在从特征继承的每个对象中编写hasType方法。

1 个答案:

答案 0 :(得分:2)

您需要使用带有ClassTag上下文绑定的类(因为这些绑定不能在特征中使用)。 如果将MyTrait替换为:

abstract class MyTrait[A <: AnyVal: ClassTag] {
    def hasType(x: AnyVal) = x match {
      case _: A => true
      case _ => false
    }
}

它将按您的预期工作