런타임에 변수 유형을 얻고 싶습니다. 어떻게해야합니까?
답변
따라서 엄밀히 말하면 “변수 유형”은 항상 존재하며 유형 매개 변수로 전달 될 수 있습니다. 예를 들면 :
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
무언가) 인지 여부를 확인할 수 있지만 예를 들어 a 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)
여기 에서는 이전 예제 의 암시 적 매개 변수처럼 작동 하지만 익명 변수를 사용하는 컨텍스트 경계 구문을 사용하고 있습니다.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 b
A ClassTag
는 기본 클래스 만 다루고 유형 매개 변수는 다루지 않는다는 점에서 제한됩니다. ,이 즉 ClassTag
위한 List[Int]
과 List[String]
동일하다 List
. 유형 매개 변수가 필요한 경우 TypeTag
대신 a 를 사용해야합니다 . TypeTag
그러나 A 는 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
물론, 그 비교가 사실로 돌아가도록하는 방법이 있지만 실제로 다루려면 몇 장의 책이 필요 TypeTag
하므로 여기서 중지하겠습니다.
마지막으로 변수의 유형에 대해 전혀 신경 쓰지 않을 수도 있습니다. 값의 클래스가 무엇인지 알고 싶을 수도 있습니다.이 경우 대답은 간단합니다.
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())}
답변
