Scala çalışma zamanı yansımaları, iç sınıflar için bile belirli bir türün tüm üyelerini alır

Dec 16 2020

Scala ile 2.12.10

Ben örtük bu durumda, çalışma zamanında bir vaka sınıfını dönüştürmek istediğiniz varsayalım Specialbir olgu sınıfına SpecialString. Örtük dönüştürme bir özellik tarafından sağlanır External. Adı SpecialString, sınıfın bildirim adı olmalıdır 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")
  }
}

Şu anda, Externalözelliği genişleten bir sınıf içinde bildirilen dönüştürücü üyeleri dolaylı olarak dönüştürebiliyorum .

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)

Ancak süper sınıfta beyan edilen üyeleri dönüştüremiyorum

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

Herhangi bir yardım?

Yanıtlar

1 DmytroMitin Dec 17 2020 at 11:51

Eğer yerine adıyla gerekli üyesini bulursanız typeSignature(ve aslında o bulduğuna) ve yazdırmak specials.head.typeSignatureve typeOf[Special]birbirlerine bir alt tür değil neden göreceksiniz

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

Dönen boş bir yöntemin türü, öğesinin Specialbir alt türü değildir Special.

Eklemelisiniz resultType. Değiştir

trait External {
  ...
  def specials: Iterable[universe.Symbol] =
    members.filter(_.typeSignature <:< typeOf[Special] )

ile

trait External {
  ...
  def specials: Iterable[universe.Symbol] =
    members.filter(_.typeSignature.resultType <:< typeOf[Special])

Scala'da çalışma zamanında sınıf parametresi veri türü nasıl bulunur