【问题标题】:Scala Reflection to generate a companion object and call the apply methodScala反射生成一个伴生对象并调用apply方法
【发布时间】:2020-04-21 21:37:42
【问题描述】:

这就是问题所在。

trait TestTrait[T, R] extends (T => R) 

// Class implementing TestTrait. This is one class, there are a number of class implementing TestTrait
class TestClass(val input: Map[String, String])extends ConfigurableDomainExtractor[String, String] {
  override def apply(value: String): String = ???
}

// Companion Object
object TestClass {
 def apply(properties: Map[String, String]): TestClass = TestClass(properties)
}

我想做的是在 util 类中定义一个方法让我们说

class CreateInstance {
  def getInstance(fullyQualifiedClassName: String, properties: Map[String, String]): TestTrait = ???

// fullyQualifiedClassName is the name of the class that needs to be instantiated using its companion object. It can be TestClass or any class implementing TestTrait
// properties is the map that needs to be pass to the apply method of the companion object.


}

当传递类名时,将首先获取一个伴随对象,然后在传递映射的伴随对象上调用apply以生成类实例,从而生成同一类的对象。

我知道我们在 scala 中有反射,我尝试了几件事但无济于事。以下是我尝试过的几件事。

  import scala.reflect.runtime.universe

def getInstance(fullyQualifiedClassName: String, properties: Map[String, String]): TestTrait = {
val runtimeMirror = universe.runtimeMirror(getClass.getClassLoader)
    val module        = runtimeMirror.staticModule(fullyQualifiedClassName)
    val obj           = runtimeMirror.reflectModule(module)

      obj.instance
        .asInstanceOf[TestTrait[String, String]]
        .apply(properties)
        .asInstanceOf[TestTrait[String, String]]

}

谁能帮我完成def getInstance 方法。 ?

【问题讨论】:

  • 在这里使用 Java 反射可能就足够了...?这要容易得多。
  • @SethTisue 如何使用 Java 反射 API?

标签: scala reflection companion-object scala-reflect


【解决方案1】:

尝试 Scala 反射

import scala.reflect.runtime.universe
import scala.reflect.runtime.universe._

def getInstance(fullyQualifiedClassName: String, properties: Map[String, String]): TestTrait[String, String] = {
  val runtimeMirror = universe.runtimeMirror(getClass.getClassLoader)
  val objSymbol = runtimeMirror.staticModule(fullyQualifiedClassName)
  val objMirror = runtimeMirror.reflectModule(objSymbol)
  val obj = objMirror.instance
  val objTyp = objSymbol.typeSignature
  val methodSymbol = objTyp.decl(TermName("apply")).asMethod
  val instanceMirror = runtimeMirror.reflect(obj)
  val methodMirror = instanceMirror.reflectMethod(methodSymbol)
  methodMirror(properties).asInstanceOf[TestTrait[String, String]]
}

getInstance("pckg.App.TestClass", Map("a" -> "b"))

或 Java 反射

def getInstance(fullyQualifiedClassName: String, properties: Map[String, String]): TestTrait[String, String] = {
  val clazz = Class.forName(fullyQualifiedClassName)
  val moduleField = clazz.getDeclaredField("MODULE$")
  val obj = moduleField.get(null) // field MODULE$ is static
  val applyMethod = clazz.getDeclaredMethod("apply", classOf[Map[_, _]])
  applyMethod.invoke(obj, properties).asInstanceOf[TestTrait[String, String]]
}

getInstance("pckg.App$TestClass$", Map("a" -> "b"))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-12
    • 1970-01-01
    • 2020-01-18
    相关资源
    最近更新 更多