Refleksi runtime scala mendapatkan semua anggota tipe tertentu bahkan untuk kelas dalam
Dengan scala 2.12.10
Misalkan saya ingin mengubah secara implisit saat runtime kelas kasus, dalam hal ini Special
menjadi kelas kasus SpecialString
. Konversi tersirat disediakan oleh suatu sifat External
. Nama untuk SpecialString
haruslah nama deklarasi kelas 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")
}
}
Saat ini saya dapat secara implisit mengubah anggota yang dinyatakan di dalam kelas yang memperluas External
sifat tersebut.
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)
Tapi saya tidak dapat mengonversi anggota yang dideklarasikan di kelas super
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
Ada bantuan?
Jawaban
Jika Anda menemukan anggota yang diperlukan berdasarkan nama daripada typeSignature
(dan itu benar-benar ditemukan kemudian) dan cetak specials.head.typeSignature
dan typeOf[Special]
Anda akan melihat mengapa salah satu bukan subtipe dari yang lain
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
Jenis metode nullary yang dikembalikan Special
bukan merupakan subtipe dari Special
.
Anda harus menambahkan resultType
. Menggantikan
trait External {
...
def specials: Iterable[universe.Symbol] =
members.filter(_.typeSignature <:< typeOf[Special] )
dengan
trait External {
...
def specials: Iterable[universe.Symbol] =
members.filter(_.typeSignature.resultType <:< typeOf[Special])
Bagaimana menemukan tipe data parameter kelas saat runtime dalam skala