Scala: Type annotation of parameter resets ClassTag to Option and spoils type matching

140 Views Asked by At

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.

1

There are 1 best solutions below

2
On BEST ANSWER

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