Let's say I have the following types
class Foo
trait Bar
Is there a way to make a method which takes in a Type parameter, T, and determine if that T is a Bar? For example,
def isBar[T <: Foo: Manifest] =
classOf[Bar].isAssignableFrom(manifest[T].erasure)
Sadly, isBar[Foo with Bar]
is false
because erasure seems to erase mixins.
Also, manifest[Foo with Bar] <:< manifest[Bar]
is false
Is this possible at all?
I looked at this question: How to tell if a Scala reified type extends a certain parent class?
but that answer doesn't work with mixed-in traits as they seem to be erased as evidenced above.
This can be achieved with TypeTags (at least 2.10M7):
scala> class Foo; trait Bar
defined class Foo
defined trait Bar
scala> import reflect.runtime.universe._
import reflect.runtime.universe._
scala> def isBar[A <: Foo : TypeTag] = typeOf[A].baseClasses.contains(typeOf[Bar].typeSymbol)
isBar: [A <: Foo](implicit evidence$1: reflect.runtime.universe.TypeTag[A])Boolean
scala> isBar[Foo]
res43: Boolean = false
scala> isBar[Foo with Bar]
res44: Boolean = true
TypeTags provide a 1:1 translation of Scala types because they represent the types the compiler knows. Therefore they are much more powerful than plain old Manifests:
scala> val fooBar = typeTag[Foo with Bar]
fooBar: reflect.runtime.universe.TypeTag[Foo with Bar] = TypeTag[Foo with Bar]
With the method tpe
we get full access to Scalas new Reflection:
scala> val tpe = fooBar.tpe // equivalent to typeOf[Foo with Bar]
tpe: reflect.runtime.universe.Type = Foo with Bar
scala> val tpe.<tab><tab> // lot of nice methods here
=:= asInstanceOf asSeenFrom baseClasses baseType contains declaration
declarations erasure exists find foreach isInstanceOf kind
map member members narrow normalize substituteSymbols substituteTypes
takesTypeArgs termSymbol toString typeConstructor typeSymbol widen
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With