2011-07-21 64 views
4

我碰到下面的代碼片段來斯卡拉郵件列表:混淆斯卡拉動態代碼段

scala> class DynamicImpl(x: AnyRef) extends Dynamic { 
    | def _select_(name: String): DynamicImpl = { 
    |  new DynamicImpl(x.getClass.getMethod(name).invoke(x)) 
    | } 
    | def _invoke_(name: String)(args: Any*) = { 
    |  new DynamicImpl(x.getClass.getMethod(name, args.map(_.asInstanceOf[AnyRef].getClass) : _*).invoke(x, args.map(_.asInstanceOf[AnyRef]) : _*)) 
    | } 
    | override def typed[T] = x.asInstanceOf[T] 
    | override def toString = "Dynamic(" + x.toString + ")" 
    | } 
defined class DynamicImpl 

scala> 

scala> implicit def toDynamic(x: Any): Dynamic = new DynamicImpl(x.asInstanceOf[AnyRef]) 
toDynamic: (x: Any)Dynamic 

scala> class Duck { 
    | def quack = "Quack!" 
    | } 
defined class Duck 

scala> class QuackingSwan { 
    | def quack = "Swack!" 
    | } 
defined class QuackingSwan 

scala> def makeQuack(d: Dynamic) { 
    | println(d.quack.typed[String]) 
    | } 
dynatype: d._select_("quack") 
makeQuack: (d: Dynamic)Unit 

scala> makeQuack(new Duck) 
Quack! 

scala> makeQuack(new QuackingSwan) 
Swack! 

scala> val s: Dynamic = "Hello, world!" 
s: Dynamic = Dynamic(Hello, world!) 

scala> s.toLowerCase 
dynatype: line8$object.$iw.$iw.s._select_("toLowerCase") 
res2: Dynamic = Dynamic(hello, world!) 

scala> s.length 
dynatype: line8$object.$iw.$iw.s._select_("length") 
res3: Dynamic = Dynamic(13) 

scala> s.isEmpty.typed[Boolean] 
dynatype: line8$object.$iw.$iw.s._select_("isEmpty") 
res4: Boolean = false 

什麼_select__invoke_這裏?

回答

1

_select__invoke_表現得像紅寶石missing_method。如果在沒有實現該方法的動態實例上調用任何方法,則調用_select__invoke_。這兩種方法可以按照你的意願實現。

在您的示例中,他們使用反射來調用x成員的實際實現。例如:

scala> val s: Dynamic = "Hello, world!" 
s: Dynamic = Dynamic(Hello, world!) 

scala> s.toLowerCase 
dynatype: line8$object.$iw.$iw.s._select_("toLowerCase") 
res2: Dynamic = Dynamic(hello, world!) 

方法toLowerCases沒有定義。因此調用方法_select_而不是參數"toLowerCase"。然後動態機制將使用反射調用x.toLowerCase並將結果包裝到新的動態實例中。

_select_被調用爲沒有參數的任何方法,而_invoke_被任何帶參數的方法調用。

+1

如果'_invoke_'是Scala的'method_missing',那麼'applyDynamic'是什麼? – missingfaktor

+1

兩個重要的事情:動態特質沒有方法,它是一個標記特徵:http://www.scala-lang.org/api/current/index.html#scala.Dynamic。動態特性仍然是實驗性的,必須通過使用-Xexperimental選項調用scala來激活。 – Christian

+0

我很困惑:http://www.assembla.com/code/scala-eclipse-toolchain/git/nodes/src/library/scala/Dynamic.scala?rev=e8607b971718f2b33db74ba9071d825c24885c62但顯然它不在Scala代碼上。 – paradigmatic