Get TypeTag[A] from Class[A]

后端 未结 2 1512
夕颜
夕颜 2020-12-01 22:04

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

2条回答
  •  星月不相逢
    2020-12-01 22:55

    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!
    

提交回复
热议问题