Search code examples
javascalatraitstype-parameter

Is it possible in Scala to use isAssignableFrom with type parameters?


I am implementing a JAX-RS service in Scala using Jersey. I would to have a generic trait for Json provider, and I need to know if the requested Class is supported by my provider. In java is not possible to know the class of a type parameter at runtime because the type erasure. But it is possible to do in scala?

This code does not work:

trait JsonProvider[A] extends MessageBodyReader[A] with MessageBodyWriter[A] {

  final def isReadable(t : Class[_],
             genericType: Type,
             annotations: Array[Annotation],
             mediaType: MediaType): Boolean = {
    t.isAssignableFrom(classOf[A]) && mediaType == MediaType.APPLICATION_JSON_TYPE
  }
}

Any suggestion? In Java the best method is to have a protected abstract method returning the class of A, in Scala too?


Solution

  • There is workaround for this. You can use Manifest type class. By using it, Scala compiler will make sure, that class information would be available at runtime. Manifest has erasure property - it's the class object for generic type.

    You can use it for method's type parameters like this:

    def printClass[T](implicit ev: Manifest[T]) =
      println(ev.erasure.getSimpleName)
    

    or simlified:

    def printClass1[T: Manifest] =
      println(manifest[T].erasure.getSimpleName)
    

    You can also use it for classes or abstract classes:

    class Printer[T: Manifest] {
      def printName = println(manifest[T].erasure.getSimpleName)
    }
    

    Unfortunately you can't use it for traits.

    Edit: As workaround, you can define trait like this:

    trait Printer[T] {
      def printName(implicit ev: Manifest[T]) =
        println(ev.erasure.getSimpleName)
    }