2016-08-25 117 views
1

我有一個類名和一個方法,其類型參數我知道,我想通過反射調用這個方法。如何通過反射調用伴侶對象上的方法?

在java中我會做這樣的事情:

Class.forName("foo").getMethod("name", ... type args...).invoke(null, ..args) 

然而在Scala中,每當我嘗試並調用我得到一個空裁判的錯誤。

我使用Scala的2.10.4

- 編輯

我曾嘗試:

$ scala 
Welcome to Scala version 2.10.5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_102). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> class Foo { def bar(x: Int) = x } 
defined class Foo 

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

scala> val foo = new Foo 
foo: Foo = [email protected] 

scala> runtimeMirror(getClass.getClassLoader).reflect(foo) 
res0: reflect.runtime.universe.InstanceMirror = instance mirror for [email protected] 

scala> res0.symbol.typeSignature.member(newTermName("bar")) 
res1: reflect.runtime.universe.Symbol = method bar 

scala> res0.reflectMethod(res1.asMethodSymbol)(42) 
<console>:15: error: value asMethodSymbol is not a member of reflect.runtime.universe.Symbol 
       res0.reflectMethod(res1.asMethodSymbol)(42) 
            ^

如從"Dynamic" method invocation with new Scala reflection API的例子似乎不工作了

以下是我正在嘗試做的一項測試:

object Test{ 
    def run(): Boolean = true 
} 

class InvokeTests extends FlatSpec with Matchers { 
    "invoke" should "do" in { 
    import scala.reflect.runtime.universe._ 

    val mirror = runtimeMirror(this.getClass.getClassLoader) 

    val moduleSymbol = mirror.moduleSymbol(Class.forName(Test.getClass.getName)) 

    val reflected = mirror.reflect(moduleSymbol) 

    val methodName = reflected.symbol.typeSignature.member(newTermName("run")) 

    reflected.reflectMethod(methodName.asMethod)() shouldBe true 
    } 
} 
+0

這這裏有一個答案:http://stackoverflow.com/questions/11062166/dynamic-method-invocation-with-new-scala-reflection-api在回答有也可以通過反射api到達伴侶對象的鏈接。 – Samar

+0

嗯,@Samar,這個例子似乎不起作用(可能自scala版本以後有變化?) – devshorts

+0

請檢查答案。它的工作正常Scala 2.11.8 – Samar

回答

2

參考scala doc reflection overview

// get runtime universe 
val ru = scala.reflect.runtime.universe 

// get runtime mirror 
val rm = ru.runtimeMirror(getClass.getClassLoader) 

// define class and companion object 
class Boo{def hey(x: Int) = x}; object Boo{def hi(x: Int) = x*x} 

// get instance mirror for companion object Boo 
val instanceMirror = rm.reflect(Boo) 

// get method symbol for the "hi" method in companion object 
val methodSymbolHi = ru.typeOf[Boo.type].decl(ru.TermName("hi")).asMethod 

// get method mirror for "hi" method 
val methodHi = instanceMirror.reflectMethod(methodSymbolHi) 

// invoke the method "hi" 
methodHi(4) // 16 
+0

我在斯卡拉2.10,這不工作 – devshorts