스칼라 런타임 리플렉션은 내부 클래스에 대해서도 특정 유형의 모든 멤버를 가져옵니다.
Dec 16 2020
스칼라 2.12.10 사용
내가 암시 적으로이 경우, 런타임에 경우 클래스를 변환 할 가정 Special
이 경우 클래스 SpecialString
. 암시 적 변환은 특성에 의해 제공됩니다 External
. 의 이름 SpecialString
은 클래스의 선언 이름이어야합니다 Special
.
import scala.reflect.runtime.universe.{runtimeMirror, typeOf}
import scala.reflect.runtime.universe
case class Special(i: Int)
case class SpecialString(s: String)
trait External {
val rm = runtimeMirror(getClass.getClassLoader)
val im = rm.reflect(this)
val members = im.symbol.typeSignature.members
def specials: Iterable[universe.Symbol] = members.filter(_.typeSignature <:< typeOf[Special] )
implicit def SpecialIntToString(s: Special): SpecialString = {
val name = im.reflectField(specials.filter(x => im.reflectField(x.asTerm).get.asInstanceOf[Special] == s).head.asTerm).symbol.toString.replace("value ", "")
SpecialString(s"name = $name")
}
}
현재는 External
특성을 확장하는 클래스 내에서 선언 된 변환 멤버를 암시 적으로 변환 할 수 있습니다.
class MyClass extends External {
val firstSpecial = Special(1)
val two = 2
val specialS: SpecialString = firstSpecial
}
class MySecondClass extends MyClass {
val specialS2: SpecialString = firstSpecial
}
val myClass = new MyClass
print(myClass.specialS) // SpecialString(name = firstSpecial)
하지만 수퍼 클래스에서 선언 된 멤버를 변환 할 수 없습니다.
class MyClass {
val firstSpecial = Special(1)
val two = 2
val specialS: SpecialString = firstSpecial
}
class MySecondClass extends MyClass with External {
val specialS2: SpecialString = firstSpecial
}
val myClass = new MyClass
print(myClass.specialS)
val mySecondClass = new MySecondClass
print(mySecondClass.specialS2) // java.util.NoSuchElementException: next on empty iterator
도움이 필요하세요?
답변
1 DmytroMitin Dec 17 2020 at 11:51
당신은 대신 이름으로 필요한 멤버를 발견하면 typeSignature
(그리고 실제로 다음 찾았다) 및 인쇄 specials.head.typeSignature
와 typeOf[Special]
하나가 다른의 서브 타입이 아닌 이유를 알 수 있습니다
trait External {
...
def specials: Iterable[universe.Symbol] =
members.filter(_.name == universe.TermName("firstSpecial") )
//members.filter(_.typeSignature.resultType <:< typeOf[Special] )
println(s"specials.head.typeSignature=${specials.head.typeSignature}=${universe.showRaw(specials.head.typeSignature)}")
println(s"typeOf[Special]=${typeOf[Special]}=${universe.showRaw(typeOf[Special])}")
println(s"specials.head.typeSignature <:< typeOf[Special]=${specials.head.typeSignature <:< typeOf[Special]}")
...
}
//specials.head.typeSignature=pckg.App.Special=NullaryMethodType(TypeRef(ThisType(pckg.App), pckg.App.Special, List()))
//typeOf[Special] =pckg.App.Special=TypeRef(ThisType(pckg.App), pckg.App.Special, List())
//specials.head.typeSignature <:< typeOf[Special]=false
반환하는 nullary 메서드 Special
의 유형이의 하위 유형이 아닙니다 Special
.
추가해야합니다 resultType
. 바꾸다
trait External {
...
def specials: Iterable[universe.Symbol] =
members.filter(_.typeSignature <:< typeOf[Special] )
와
trait External {
...
def specials: Iterable[universe.Symbol] =
members.filter(_.typeSignature.resultType <:< typeOf[Special])
스칼라에서 런타임에 클래스 매개 변수 데이터 유형을 찾는 방법