我想在运行时获取变量的类型 [英] I want to get the type of a variable at runtime

查看:21
本文介绍了我想在运行时获取变量的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在运行时获取变量的类型.我该怎么做?

I want to get the type of a variable at runtime. How do I do this?

推荐答案

所以,严格来说,变量的类型"始终存在,并且可以作为类型参数传递.例如:

So, strictly speaking, the "type of a variable" is always present, and can be passed around as a type parameter. For example:

val x = 5
def f[T](v: T) = v
f(x) // T is Int, the type of x

但是取决于你想做什么,这对你没有帮助.例如,可能不想知道变量的类型是什么,而是想知道的类型是否是某种特定类型,例如:

But depending on what you want to do, that won't help you. For instance, may want not to know what is the type of the variable, but to know if the type of the value is some specific type, such as this:

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].

Here it doesn't matter what is the type of the variable, Any. What matters, what is checked is the type of 5, the value. In fact, T is useless -- you might as well have written it def f(v: Any) instead. Also, this uses either ClassTag or a value's Class, which are explained below, and cannot check the type parameters of a type: you can check whether something is a List[_] (List of something), but not whether it is, for example, a List[Int] or List[String].

另一种可能是您想要reify变量的类型.也就是说,您想将类型转换为值,以便您可以存储它、传递它等等.这涉及反射,您将使用 ClassTagTypeTag.例如:

Another possibility is that you want to reify the type of the variable. That is, you want to convert the type into a value, so you can store it, pass it around, etc. This involves reflection, and you'll be using either ClassTag or a TypeTag. For example:

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"

ClassTag 还可以让您使用在 match 上收到的类型参数.这行不通:

A ClassTag will also let you use type parameters you received on match. This won't work:

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 示例中的隐式参数,但使用匿名变量.

Here I'm using the context bounds syntax, B : ClassTag, which works just like the implicit parameter in the previous ClassTag example, but uses an anonymous variable.

还可以从值的 Class 中获取 ClassTag,如下所示:

One can also get a ClassTag from a value's Class, like this:

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

ClassTag 的局限性在于它仅涵盖基类,而不涵盖其类型参数.也就是说,List[Int]List[String]ClassTag 是相同的,List.如果需要类型参数,则必须改用 TypeTag.但是,由于 JVM 的擦除TypeTag 不能从值中获得,也不能用于模式匹配.

A ClassTag is limited in that it only covers the base class, but not its type parameters. That is, the ClassTag for List[Int] and List[String] is the same, List. If you need type parameters, then you must use a TypeTag instead. A TypeTag however, cannot be obtained from a value, nor can it be used on a pattern match, due to JVM's erasure.

带有 TypeTag 的示例可能会变得非常复杂——即使比较两个类型标签也不是很简单,如下所示:

Examples with TypeTag can get quite complex -- not even comparing two type tags is not exactly simple, as can be seen below:

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

当然,有一些方法可以让这种比较返回真值,但要真正涵盖 TypeTag 需要几本书的章节,所以我就到此为止.

Of course, there are ways to make that comparison return true, but it would require a few book chapters to really cover TypeTag, so I'll stop here.

最后,也许你根本不关心变量的类型.也许你只是想知道一个值的类别是什么,在这种情况下答案很简单:

Finally, maybe you don't care about the type of the variable at all. Maybe you just want to know what is the class of a value, in which case the answer is rather simple:

val x = 5
x.getClass // int -- technically, an Int cannot be a class, but Scala fakes it

不过,最好更具体地说明您要完成的工作,以便回答更切中要害.

It would be better, however, to be more specific about what you want to accomplish, so that the answer can be more to the point.

这篇关于我想在运行时获取变量的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆