런타임에 변수 유형을 얻고 싶습니다. 어떻게해야합니까?
답변:
따라서 엄밀히 말하면 "변수 유형"은 항상 존재하며 유형 매개 변수로 전달 될 수 있습니다. 예를 들면 :
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
그러나 달성하고자하는 것에 대해 더 구체적으로 설명하는 것이 더 낫습니다. 그래야 답이 요점에 더 가깝게 될 수 있습니다.
Int
이다 Any
, 그러나 Any
아니다 Int
. 그것은 Scala 2.10에서 작동하고 Scala 2.11에서 작동 해야하며 왜 그렇지 않은지 모르겠습니다.
a match { case _: B => ...
는 변수 a
의 유형이 아닌 변수의 실제 값 유형을 테스트합니다 a
. 스칼라 2.10.6에서 말한 내용을 반환한다는 점에서 맞습니다. 하지만 버그 여야합니다. 스칼라 2.11.8에서는 실제 값의 유형이 테스트됩니다.
질문이 불완전하다고 생각합니다. 어떤 유형 클래스의 유형 정보를 얻으려면 다음과 같이하십시오.
지정한대로 인쇄하려면 다음을 수행하십시오.
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
목적을 해결할 수 있습니다.
typeof x
와 같이 여기 manOf(x)
에 데이터 유형을 말하십시오!
에 의해 경우 변수의 유형 당신은 객체의 런타임 클래스를 의미하는 변수 포인트는, 당신은 모든 객체가 가지고있는 클래스 참조를 통해이를 얻을 수 있습니다.
val name = "sam";
name: java.lang.String = sam
name.getClass
res0: java.lang.Class[_] = class java.lang.String
그러나 변수가 선언 된 유형을 의미하는 경우이를 얻을 수 없습니다. 예를 들면
val name: Object = "sam"
그러면 String
위의 코드에서 여전히 다시 얻을 수 있습니다.
name.getClass.getSimpleName
더 읽기 쉬운 출력을 위해 할 수도 있습니다
나는 그것을 테스트했고 효과가 있었다
val x = 9
def printType[T](x:T) :Unit = {println(x.getClass.toString())}
5
은의 인스턴스Int
이자의 인스턴스이기 때문Any
입니다. 그 외에도에서, 당신의 설명 : 완벽했다