Reputation: 7288
I'm currently unable to wrap my head around Scala's TypeTag reflection API. There are very little information to find on the web and all trial and error attempts are leading nowhere.
def doStuff[T: TypeTag]( param: String ): SomeStuff[E] =
{
val t = typeOf[T]
if( <t extends one specific Trait from my application and is an object> )
{
<retrieve that companion object and return one of its values>
}
else
{
t match
{
case x if x =:= typeOf[String] => doOtherStuff[String]( param )
case x if x =:= typeOf[Int] => doOtherStuff[Int]( param )
...
}
}
}
The pattern matching with Scala's predefined Types is working. However I didn't manage to check if the supplied generic argument inherits my specific Trait and later on retrieve the companion object of the actual class behind T
. Trying with a straight forward typeOf[MyTrait[_, T]]
is being rejected by the compiler telling me that no TypeTag is available for MyTag. How do I create it?
In addition the Trait's nasty generic signature MyTrait[M <: MyTrait[M, E], E <: Entity[M, E]]
is exacerbating the whole thing.
Besides some helpful ideas to solve this problem I highly appreciate any further reading links (I've read all on SO though).
Upvotes: 2
Views: 1934
Reputation: 14842
Use the following to test if it is an object (from this question):
typeOf[Test] <:< typeOf[Singleton]
You can use existential types to get a TypeTag
of your trait:
typeOf[MyTrait[M, T] forSome { type M <: MyTrait[M, T] }]
This works if you have a TypeTag[T]
in scope and is bound as following:
T <: Entity[_,T]
Minimal example:
trait Entity[M, E]
trait MyTrait[M <: MyTrait[M, E], E <: Entity[M, E]]
class MyEnt extends Entity[Test, MyEnt]
class Test extends MyTrait[Test, MyEnt]
def getType[T <: Entity[_, T] : TypeTag] =
typeOf[MyTrait[M,T] forSome { type M <: MyTrait[M,T] }]
typeOf[Test] <:< getType[MyEnt]
//| res0: Boolean = true
However, this will not work in your case, since T
is not properly bounded. Hence you'll have to test against this (with some help from here):
val mts = typeOf[MyTrait[_,_]].typeSymbol
typeOf[Test].baseType(mts) match {
case TypeRef(_, _, List(_, t)) if t <:< typeOf[MyEnt] => true
case _ => false
}
Upvotes: 2