Confusion Scala Scanned Dynamic Snippet

I met the following code snippet on the Scala mailing list:

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 

What is _select_ and _invoke_ here?

+4
source share
1 answer

_select_ and _invoke_ behave like a Ruby missing_method . When a method is called in a dynamic instance that does not implement the method, _select_ or _invoke_ is _select_ _invoke_ . These two methods can be implemented as you wish.

In your example, they use reflection to invoke the actual implementation of member x . For instance:

 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!) 

The toLowerCase method toLowerCase not defined in s . Thus, the _select_ method _select_ called with the argument "toLowerCase" . The dynamic engine then calls x.toLowerCase with reflection and completes the result in a new dynamic instance.

_select_ is called for any method with no arguments, and _invoke_ is called for any method with arguments.

+1
source

All Articles