2013-05-09 1 views
0

У меня есть несколько вариантов использования для этого, вокруг идеи взаимодействия между существующими библиотеками Java и новым кодом Scala. Вариант использования, который я выбрал, самый легкий, я думаю.Есть ли какой-нибудь способ создания нового объекта Scala из класса Java

Use Case:

Я работаю на предоставление JUnit Runner для некоторых тестов SCALA (так что я могу получить мой прекрасный красный/зеленый бар в Затмении) Бегун должен иметь конструктор с 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 или создать M yTestClass, которые являются объектами Scala. Я бы предпочел использовать Scala Reflection, но я также хочу использовать стандартную банку Junit.

То, что я сделал

Следующие вопросы потока Stackover были образовательными, но не та же самая проблема. Были ближайшие вопросы, которые я мог бы найти

дискуссию по Environments, Вселенных и зеркала в http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html было хорошо, и аналогичные документы на другой лестницу отражения также помогли. В основном это касается отражения Скалы.

Я просмотрел Скаладоки, но мне не хватало знаний о отражении Скала, чтобы я мог получить то, что хотел от них.

Edit: Как спросил здесь код класса, который создается за счет отражения

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

    println("starting") 

    val x= "xxx" 
} 

Так самое интересное заключается в том, что решение, предложенное ниже, используя поле, называемое МОДУЛЬ $ ничего не печатает и значение x равно нулю

+0

Я обнаружил, что вал экземпляр = clazz.getField («МОДУЛЬ $») получить (нуль) работает, чтобы получить. объект. Кажется, это немного «волшебный», это рекомендуемый способ? –

+0

Этот вопрос очень хороший http://stackoverflow.com/questions/11020746/get-companion-object-instance-with-new-scala-reflection-api/11031443#11031443 –

ответ

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" 
} 
+0

Это прекрасно работает.Теперь у меня есть экземпляр, я подозреваю, что я могу использовать отражение scala от него, а не класса. –

+0

К сожалению, пока это работает, он не вызывает код, который создает экземпляры полей в сопутствующем объекте. Например, если у меня есть val x = 1 внутри объекта-компаньона, java-отражение в созданном экземпляре возвращает null. –

+0

Можете ли вы представить структуру двух классов, которые вы упомянули здесь в своем вопросе, чтобы я мог предоставить решение? Это пример на основе класса или пример на основе объекта? Просто хочу видеть отношения класса/компаньона и то, что вы хотите, чтобы я мог дать ответ. – cmbaxter