I have createOld method that I need to override and I cannot change it. I would like to use TypeTag to pattern match provided type in createN
So it is not very safe and correct (cause you don't use the power of scala type system), but you can make (using your logic) to do the following:
def createNew[A](implicit t: TypeTag[A]): A = {
val result: Any = t.tpe.toString match {
case "C1" => new C1
case "C2" => new C2
}
result.asInstanceOf[A]
}
createNew[C1] //> its all ok
createNew[C2] //> its all ok
createNew[C3] //> crashes here; lets pretend we got C3 class
To use it with createOld, just pass implicit argument:
def createOld[A](c: Class[A])(implicit t: TypeTag[A]): A = createNew[A]
createOld[C1] //> its all ok
createOld[C2] //> its all ok
createOld[C3] //> crashes here; lets pretend we got C3 class
I think I should not tell you twice that it is not very good.
We can improve this code by using shapeless:
Lets create a poly function, which has a TypeTag as an argument:
import shapeless._; import scala.reflect.runtime.universe._;
def getTypeTag[T](implicit t: TypeTag[T]) = t //> to get TypeTag of a class
// here is low prority implicit
trait createPolyNewErr extends Poly1 {
implicit def newErr[T] = at[T](_ => "Error can not create object of this class")
}
object createPolyBew extends createPolyNewError {
implicit def newC1 = at[TypeTag[C1]](_ => new C1)
implicit def newC2 = at[TypeTag[C2]](_ => new C2)
}
createPolyNew(getTypeTag[C1]) //> success
createPolyNew(getTypeTag[C2]) //> success
createPolyNew(getTypeTag[C3]) //> String: Error can not create object of this class no crash!
We also can write a function, in order not to use function getTypeTag[T] every time:
def createPoly[T]
(implicit t: TypeTag[T],
cse: poly.Case[createPolyNew.type, TypeTag[T] :: HNil]) = cse(t)
createPoly[C1] //> its all ok
createPoly[C2] //> its all ok
createPoly[C3] //> String: Error can not create object of this class no crash!