Question

I have a number of use cases for this, all around the idea of interop between existing Java libraries and new Scala Code. The use case I've selected is the easiest I think.

Use Case:

I working on providing a JUnit Runner for some scala tests (so that I can get my lovely red / green bar in Eclipse) The runner needs to have a constructor with a java class as a parameter. So in Scala I can do the following:

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

When I use either

@RunWith(MyRunner)
object MyTestObject 

or

@RunWith(MyRunner)
class MyTestClass

then the runner is indeed instantiated correctly, and is passed a suitable class object

Unfortunately what i want to do now is to "get hold of" the object MyTestObject, or create a MyTestClass, which are both Scala entities. I would prefer to use Scala Reflection, but I also want to use the standard Junit jar.

What I have done

The following Stackover flow questions were educational, but not the same problem. There were the nearest questions I could find

The discussion on Environments, Universes and Mirrors in http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html was good, and the similar documents on other scala reflection also helped. Mostly through it is about the Scala reflection.

I browsed the Scaladocs, but my knowledge of Scala reflection wasn't enough (yet) to let me get what I wanted out of them.

Edit: As asked here is the code of the class that is being created by reflection

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

  println("starting")

  val x= "xxx"
}

So the interesting thing is that the solution proposed below using the field called MODULE$ doesn't print anything and the value of x is null

Était-ce utile?

La solution

This solution works fine if you want to use plan old java reflection. Not sure if you can use scala reflection given all you will have is a Class[_] to work with:

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"
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top