0

我有很多用例,围绕着现有 Java 库和新 Scala 代码之间的互操作的想法。我选择的用例是我认为最简单的。

用例:

我正在为一些 scala 测试提供一个 JUnit Runner(这样我就可以在 Eclipse 中获得我可爱的红色/绿色条) runner 需要一个带有 java 类作为参数的构造函数。因此,在 Scala 中,我可以执行以下操作:

class MyRunner(val clazz: Class[Any]) extends Runner {
  def getDescription(): Description 
  def run(notifier: RunNotifier)
}

当我使用

@RunWith(MyRunner)
object MyTestObject 

或者

@RunWith(MyRunner)
class MyTestClass

那么跑步者确实被正确地实例化了,并且被传递了一个合适的类对象

不幸的是,我现在要做的是“掌握”对象 MyTestObject,或者创建一个 MyTestClass,它们都是 Scala 实体。我更喜欢使用 Scala Reflection,但我也想使用标准的 Junit jar。

我做了什么

以下 Stackover 流程​​问题具有教育意义,但不是同一个问题。我能找到最近的问题

http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html中关于环境、宇宙和镜像的讨论很好,关于其他 scala 反射的类似文档也有帮助。通过它主要是关于 Scala 反射。

我浏览了 Scaladocs,但我对 Scala 反射的了解还不足以让我从它们那里得到我想要的东西。

编辑:这里问的是反射创建的类的代码

@RunWith(classOf[MyRunner])
object Hello2 extends App {

  println("starting")

  val x= "xxx"
}

所以有趣的是,下面使用名为 MODULE$ 的字段提出的解决方案不打印任何内容,并且 x 的值为 null

4

1 回答 1

2

如果您想使用计划旧 java 反射,此解决方案可以正常工作。不确定您是否可以使用 scala 反射,因为您将拥有的只是一个Class[_]可以使用的:

object ReflectTest {
  import collection.JavaConversions._
  def main(args: Array[String]) {    
    val fooObj = instantiate(MyTestObject.getClass())
    println(fooObj.foo)
    val fooClass = instantiate(classOf[MyTestClass])
    println(fooClass.foo)
  }

  def instantiate(clazz:Class[_]):Foo = {
    val rm = ru.runtimeMirror(clazz.getClassLoader())
    val declaredFields = clazz.getDeclaredFields().toList
    val obj = declaredFields.find(field => field.getName() == "MODULE$") match{
      case Some(modField) => modField.get(clazz)
      case None => clazz.newInstance()
    }
    obj.asInstanceOf[Foo]
  }
}

trait Foo{
  def foo:String
}

object MyTestObject extends Foo{
  def foo = "bar"
}

class MyTestClass extends Foo{
  def foo = "baz"
}
于 2013-05-09T11:51:29.530 回答