Je veux obtenir le type d’une variable à l’exécution. Comment puis-je faire cela?
Ainsi, à proprement parler, le “type d’une variable” est toujours présent et peut être transmis en tant que paramètre de type. Par exemple:
val x = 5 def f[T](v: T) = v f(x) // T is Int, the type of x
Mais selon ce que vous voulez faire , cela ne vous aidera pas. Par exemple, peut vouloir ne pas savoir quel est le type de la variable, mais savoir si le type de la valeur est un type spécifique, tel que ceci:
val x: Any = 5 def f[T](v: T) = v match { case _: Int => "Int" case _: Ssortingng => "Ssortingng" case _ => "Unknown" } f(x)
Ici, peu importe le type de la variable, Any
. Ce qui compte, ce qui est vérifié, c’est le type de 5
, la valeur. En fait, T
est inutile – vous auriez aussi bien pu l’écrire à la place def f(v: Any)
. En outre, cela utilise soit ClassTag
ou une Class
de valeur, qui sont expliquées ci-dessous, et ne peut pas vérifier les parameters de type d’un type: vous pouvez vérifier si quelque chose est une List[_]
( List
de quelque chose), mais pas Par exemple, une List[Int]
ou une List[Ssortingng]
.
Une autre possibilité est que vous souhaitiez réifier le type de la variable. C’est-à-dire que vous voulez convertir le type en une valeur, de manière à pouvoir la stocker, la transmettre, etc. Cela implique une reflection et vous utiliserez ClassTag
ou TypeTag
. Par exemple:
val x: Any = 5 import scala.reflect.ClassTag def f[T](v: T)(implicit ev: ClassTag[T]) = ev.toSsortingng f(x) // returns the ssortingng "Any"
Un ClassTag
permettra également d’utiliser les parameters de type que vous avez reçus lors du match
. Cela ne marchera pas:
def f[A, B](a: A, b: B) = a match { case _: B => "A is a B" case _ => "A is not a B" }
Mais cela va:
val x = 'c' val y = 5 val z: Any = 5 import scala.reflect.ClassTag def f[A, B: ClassTag](a: A, b: B) = a match { case _: B => "A is a B" case _ => "A is not a B" } f(x, y) // A (Char) is not a B (Int) f(x, z) // A (Char) is a B (Any)
J’utilise ici la syntaxe des limites de contexte , B : ClassTag
, qui fonctionne exactement comme le paramètre implicite de l’exemple ClassTag
précédent, mais utilise une variable anonyme.
On peut également obtenir un ClassTag
partir d’une Class
de valeur, comme ceci:
val x: Any = 5 val y = 5 import scala.reflect.ClassTag def f(a: Any, b: Any) = { val B = ClassTag(b.getClass) ClassTag(a.getClass) match { case B => "a is the same class as b" case _ => "a is not the same class as b" } } f(x, y) == f(y, x) // true, a is the same class as b
Un ClassTag
est limité car il ne couvre que la classe de base, mais pas ses parameters de type. En d’autres ClassTag
, le ClassTag
pour List[Int]
et List[Ssortingng]
est le même, List
. Si vous avez besoin de parameters de type, vous devez utiliser un TypeTag
place. Un TypeTag
cependant, ne peut pas être obtenu à partir d’une valeur, et ne peut pas non plus être utilisé pour une correspondance de modèle, en raison de l’ effacement de la JVM.
Les exemples avec TypeTag
peuvent devenir assez complexes – ne pas même comparer deux tags de type n’est pas tout à fait simple, comme on peut le voir ci-dessous:
import scala.reflect.runtime.universe.TypeTag def f[A, B](a: A, b: B)(implicit evA: TypeTag[A], evB: TypeTag[B]) = evA == evB type X = Int val x: X = 5 val y = 5 f(x, y) // false, X is not the same type as Int
Bien sûr, il existe des moyens de rendre cette comparaison vraie, mais cela nécessiterait quelques chapitres de livre pour vraiment couvrir TypeTag
, alors je vais m’arrêter ici.
Enfin, peut-être que vous ne vous souciez pas du type de la variable. Peut-être que vous voulez juste savoir quelle est la classe d’une valeur, auquel cas la réponse est plutôt simple:
val x = 5 x.getClass // int -- technically, an Int cannot be a class, but Scala fakes it
Il serait cependant préférable d’être plus précis sur ce que vous voulez accomplir, afin que la réponse soit plus pertinente.
Je pense que la question est incomplète. si vous voulez dire que vous souhaitez obtenir les informations de type d’une classe de classe, puis ci-dessous:
Si vous souhaitez imprimer comme vous l’avez spécifié, alors:
scala> def manOf[T: Manifest](t: T): Manifest[T] = manifest[T] manOf: [T](t: T)(implicit evidence$1: Manifest[T])Manifest[T] scala> val x = List(1,2,3) x: List[Int] = List(1, 2, 3) scala> println(manOf(x)) scala.collection.immutable.List[Int]
Si vous êtes en mode repl, alors
scala> :type List(1,2,3) List[Int]
Ou si vous voulez juste savoir ce que le type de classe alors comme @monkjack explique "ssortingng".getClass
pourrait résoudre le but
Si, par le type d’une variable, vous voulez dire la classe d’exécution de l’object sur lequel la variable pointe, vous pouvez l’obtenir via la référence de classe dont disposent tous les objects.
val name = "sam"; name: java.lang.Ssortingng = sam name.getClass res0: java.lang.Class[_] = class java.lang.Ssortingng
Si toutefois vous voulez dire le type que la variable a été déclarée, alors vous ne pouvez pas l’obtenir. Par exemple, si vous dites
val name: Object = "sam"
alors vous aurez toujours une Ssortingng
retour du code ci-dessus.
j’ai testé ça et ça a fonctionné
val x = 9 def printType[T](x:T) :Unit = {println(x.getClass.toSsortingng())}