I have a trait with a type parameter. Inside this trait I want to define a method which checks if an object matches the type parameter. So far, this works, as I want it to work:
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
The problem occurs when MyTrait
-objects are parameters of a class, like here:
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"
So bassicly the type annotation Seq[MyTrait[_]]
of the parameter turns my ClassTag to a general Object and ruins type matching. I really would like to avoid writing the hasType
method in each object that inherits from the trait.
You need to use a class with a ClassTag
context bound (since those bounds are not utilizable in traits).
If you replace MyTrait
as:
abstract class MyTrait[A <: AnyVal: ClassTag] {
def hasType(x: AnyVal) = x match {
case _: A => true
case _ => false
}
}
it will works as you expect