Confusing Scala Dynamic code snippet -
i came across following code snippet on 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's _select_
, _invoke_
here?
_select_
, _invoke_
behave ruby missing_method
. when method called on dynamic instance not implement method, _select_
or _invoke_
called instead. 2 methods can implemented wish.
in example, use reflection call actual implementation of x
member. 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 method tolowercase
not defined in s
. method _select_
called instead argument "tolowercase"
. dynamic mechanism call x.tolowercase
using reflection , wrap result in new dynamic instance.
_select_
called method without arguments, while _invoke_
called method arguments.
Comments
Post a Comment