2017-04-10 5 views
1

Je voudrais faire une classe de cas Bla qui prend un paramètre de type A et qui connaît le type de A lors de l'exécution (il le stocke dans son champ info).TypeTag pour les classes de cas

Ma tentative est illustrée dans l'exemple ci-dessous. Le problème est que cet exemple ne compile pas.

case class Bla[A](){ 
    val info=Run.paramInfo(this) // this does not compile 
} 
import scala.reflect.runtime.universe._ 

object Run extends App{ 
    val x=Bla[Int] 
    def paramInfo[T](x:T)(implicit tag: TypeTag[T]): String = { 
    val targs = tag.tpe match { case TypeRef(_, _, args) => args } 
    val tinfo=s"type of $x has type arguments $targs" 
    println(tinfo) 
    tinfo 
    } 
    paramInfo(x) 
} 

Cependant, quand je commente val info=Run.paramInfo(this) alors le programme fonctionne très bien et impressions:

type de Bla() est de type arguments Liste (Int)

Y at-il un moyen de faire cet exemple ci-dessous compiler? (ou d'une autre manière atteindre le même objectif, c'est-à-dire qu'une classe de cas est consciente du type de son type type?)

Répondre

2

Vous avez juste besoin de passer le paramètre tag de type implicite au constructeur de la classe case (sinon le les informations de type est perdue avant d'appeler paraInfo qui l'exige):

case class Bla[A : TypeTag]() { ... } 

ce qui est un raccourci pour:

case class Bla[A](implicit tag: TypeTag[A]) { ... } 
+0

Merci, cela a fonctionné. – jhegedus

3

il y a peu d'intérêt à l'aide d'API basées sur la réflexion pour cela, informes a une classe de types qui expose COMPI le temps de l'information à l'exécution en utilisant une macro implicite.

import shapeless.Typeable 


class Test[T : Typeable] { 
    def info: String = implicitly[Typeable[T]].describe 
} 

Il est relativement facile de rouler votre propre chose ici, avec l'inconvénient supplémentaire d'avoir à compiler la macro implicite dans une unité de compilation différente de tout ce qui est de l'utiliser.

+0

Merci, la valeur de 'info' n'est-elle pas déterminée lors de la compilation lors de l'utilisation de' TypeTag'? – jhegedus

+1

@jhegedus Non, 'TypeTag' est une API de réflexion, c'est une version plus évoluée de' Class [_] 'de Java. – flavian

+0

Il semble que la valeur de TypeTag soit décidée au moment de la compilation: "Comme scala.reflect.Manifest, les TypeTags peuvent être considérés comme des objets qui transportent toutes les informations de type disponibles au moment de la compilation, par exemple, TypeTag [T ] encapsule la représentation du type d'exécution de certains types de compilation T. Notez cependant que TypeTags doit être considéré comme un remplacement plus complet de la notion antérieure à 2.10 d'un manifeste, qui est en outre entièrement intégrée à la réflexion de Scala. " http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html – jhegedus