2010-06-14 233 views
30

說,我有以下幾點:如何使用反射調用Scala對象方法?

trait SomeTrait { 
    def someMethod: String; 
} 

object SomeObject extends SomeTrait { 
    def someMethod = "something"; 
} 

我想稱之爲「的someMethod」使用反射,因爲我有對象的字符串名字。 類似於:

val objectName = "SomeObject" 
val someTrait:SomeTrait = ???.asInstanceOf[SomeTrait] 
someTrait.someMethod 

或類似的東西。

由於

回答

13

對於類,這可以很容易地使用標準的Java反射classOf方法完成。對於Scala的對象,它是更多的工作,但它仍然可以做到:


trait SomeTrait { def someMethod: String} 
object SomeObject extends SomeTrait { def someMethod = "something"} 

class SomeClass extends SomeTrait { def someMethod = "something"} 

object Main { 
def main(args:Array[String]) = { 
    val someClassTrait:SomeTrait = Class.forName("SomeClass").newInstance().asInstanceOf[SomeTrait] 
    println("calling someClassTrait: " + someClassTrait.someMethod) 
    val objectName = "SomeObject$" 
    val cons = Class.forName(objectName).getDeclaredConstructors(); 
    cons(0).setAccessible(true); 
    val someObjectTrait:SomeTrait = cons(0).newInstance().asInstanceOf[SomeTrait] 
    println("calling someObjectTrait: " + someObjectTrait.someMethod) 
    } 
} 

//prints: 
calling someClassTrait: something 
calling someObjectTrait: something 
+2

我認爲它打破伴侶(單身)對象的客戶期望,如果你創建它的新實例。 – 2010-06-15 07:36:54

+0

Arjan - 謝謝。這正是我所期待的。 Thomas - 確實如此。但是你總是可以將代碼包裝在一個對象工廠中,並自己提供單例行爲。 – sanjib 2010-06-15 17:10:43

19
def companion[T](name : String)(implicit man: Manifest[T]) : T = 
    Class.forName(name + "$").getField("MODULE$").get(man.erasure).asInstanceOf[T] 

val result = companion[SomeTrait]("SomeObject").someMethod 
+0

這甚至更好。謝謝托馬斯。 – sanjib 2010-06-15 17:11:02

+2

你需要清單嗎?我發現'Class.forName(name +「$」)。getField(「MODULE $」)。get(null)'就足夠了。這是允許的靜態字段。 – 2013-06-01 17:44:32

+1

2.10如何用反射翻譯? – bhericher 2013-06-27 14:15:57

12

在Scala 2.10,我們可以用模塊的反思:

import scala.reflect.runtime.universe 

val runtimeMirror = universe.runtimeMirror(getClass.getClassLoader) 
val module = runtimeMirror.staticModule("SomeObject") 
val obj = runtimeMirror.reflectModule(module) 
val someTrait:SomeTrait = obj.instance.asInstanceOf[SomeTrait] 
someTrait.someMethod