Scala 反射:强制初始化对象成员 [英] Scala reflection: Force init of object members

查看:43
本文介绍了Scala 反射:强制初始化对象成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Scala fiddle 这里

import scala.reflect.ClassTag
import scala.language.existentials

class SomeClass[T <: SomeClass[T, R], R] extends EarlyInit[T, R] {}

trait EarlyInit[T <: SomeClass[T, R], R] {
    self: SomeClass[T, R] =>

      val clazz = getClass.getSuperclass
      val potentialFields = clazz.getDeclaredClasses.toList

      potentialFields.foreach {
        field => {
          // This correctly prints out fields of object members.
          // but invokation throws an error every time.
          println(s"${field.getName}")
        }
      }
}

class SomeThing extends SomeClass[SomeThing, Any] {
    val stringTest = "test"
    object name
    object test
}

object SomeThing extends SomeThing {}

val x = SomeThing

如何使用反射访问和初始化对象成员(nametest)?

How do I access and initialise object members(name and test) with reflection?

推荐答案

您可以使用 Scala 反射 API 来实现:

You can achieve this with scala reflection API:

import scala.reflect.runtime.universe._

class SomeClass[T <: SomeClass[T, R]: TypeTag, R] extends EarlyInit[T] {}

class EarlyInit[T: TypeTag] {
  val mirror = runtimeMirror(this.getClass.getClassLoader)
  val reflection  = mirror.reflect(this)

  typeTag[T].tpe.members.filter(_.isModule).foreach(m => reflection.reflectModule(m.asModule).instance)
}

class SomeThing extends SomeClass[SomeThing, Any] {
  val stringTest = "test"

  object name {
    println("name initialized")
  }
  object test {
    println("test initialized")
  }
}

object SomeThing extends SomeThing {}

val x = SomeThing

您需要使 EarlyInit 成为一个类才能获得 TypeTag 证据.然后你只需搜索所有模块并访问它们(它们将在过程中初始化)

You need to make EarlyInit a class in order to be able to get a TypeTag evidence. Then you just search for all modules and access them (they would be initialized in the process)

您还可以稍微简化 EarlyInit 并去掉类型参数.你实际上可以直接从镜像中获取thisType:

You can also simplify EarlyInit a bit and get rid of type parameter. You actually can get a Type of this directly from mirror:

trait EarlyInit {
  val mirror = runtimeMirror(this.getClass.getClassLoader)
  val reflection  = mirror.reflect(this)

  mirror
    .classSymbol(this.getClass)
    .toType
    .members
    .filter(_.isModule)
    .foreach(m => reflection.reflectModule(m.asModule).instance)
}

这篇关于Scala 反射:强制初始化对象成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆