4 ответов:
Таким образом, строго говоря, "тип переменной" всегда присутствует и может передаваться как параметр типа. Например:
val x = 5 def f[T](v: T) = v f(x) // T is Int, the type of xНо в зависимости от того, что вы хотите сделать, это тебе не поможет. Например, может потребоваться не знать, какой тип переменной, а знать, является ли тип значения каким-то конкретным типом, например:
val x: Any = 5 def f[T](v: T) = v match { case _: Int => "Int" case _: String => "String" case _ => "Unknown" } f(x)Здесь не имеет значения, какой тип переменной,
Any. Что имеет значение, что есть проверяется тип5, значение. На самом деле,Tбесполезно-вы могли бы написать егоdef f(v: Any)вместо этого. Кроме того, это использует либоClassTag, либо значениеClass, которые объясняются ниже, и не может проверить параметры типа типа: вы можете проверить, является ли что-тоList[_](Listчего-то), но не является ли это, например,List[Int]илиList[String].Другая возможность заключается в том, что вы хотитеовеществить тип переменной. То есть вы хотите обратить тип в значение, так что вы можете хранить его, передавать его и т.д. Это предполагает рефлексию, и вы будете использовать либо
ClassTag, либоTypeTag. Например:val x: Any = 5 import scala.reflect.ClassTag def f[T](v: T)(implicit ev: ClassTag[T]) = ev.toString f(x) // returns the string "Any"A
ClassTagтакже позволит вам использовать параметры типа, полученные наmatch. Это не сработает:def f[A, B](a: A, b: B) = a match { case _: B => "A is a B" case _ => "A is not a B" }Но это будет:
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)Здесь я использую синтаксис context bounds ,
B : ClassTag, который работает так же, как неявный параметр в предыдущем примереClassTag, но использует анонимный переменная.Можно также получить
ClassTagиз значенияClass, например: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 bA
ClassTagограничен тем, что он охватывает только базовый класс, но не его параметры типа. То естьClassTagдляList[Int]иList[String]- это одно и то же,List. Если вам нужны параметры типа, то вы должны использоватьTypeTagвместо этого. ATypeTag, однако, не может быть получен из значения, и он не может быть использован для сопоставления шаблона, из-за стирания JVM.Примеры с
TypeTagмогут получиться довольно сложными -- даже не сравнить два типа тегов не совсем просто, как можно увидеть ниже:Конечно, есть способы сделать это сравнение истинным, но для того, чтобы его действительно охватить, потребуется несколько глав книги, поэтому я остановлюсь здесь.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Наконец, возможно, вас вообще не волнует тип переменной. Может быть, вы просто хотите знать, что такое класс значения, и в этом случае ответ довольно прост:
Однако было бы лучше, если бы их было больше. конкретизируйте, чего вы хотите достичь, чтобы ответ был более точным.val x = 5 x.getClass // int -- technically, an Int cannot be a class, but Scala fakes it
Я думаю, что вопрос неполон. если вы имели в виду, что хотите получить информацию о типе некоторого класса, то ниже:
Если вы хотите напечатать, как вы указали, то:
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]Если вы находитесь в режиме repl, то
scala> :type List(1,2,3) List[Int]Или если вы просто хотите знать, что тип класса, то, как объясняет @monkjack
"string".getClass, может решить цель
Если подтипом переменной вы подразумеваете класс среды выполнения объекта, на который указывает переменная, то вы можете получить это через ссылку на класс, которую имеют все объекты.
val name = "sam"; name: java.lang.String = sam name.getClass res0: java.lang.Class[_] = class java.lang.StringЕсли вы, однако, имеете в виду тип, в котором переменная была объявлена, то вы не можете получить это. Например, если вы говорите
val name: Object = "sam"Тогда вы все равно получите
Stringобратно из приведенного выше кода.
Я проверил это, и это сработало
val x = 9 def printType[T](x:T) :Unit = {println(x.getClass.toString())}
Comments