Запутанный фрагмент кода Scala Dynamic - PullRequest
4 голосов
/ 21 июля 2011

Я обнаружил следующий фрагмент кода в списке рассылки Scala:

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 Ответ

1 голос
/ 21 июля 2011

_select_ и _invoke_ ведут себя как Ruby 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!)

Метод toLowerCase не определен в s.Таким образом, метод _select_ вызывается вместо аргумента "toLowerCase".Затем динамический механизм вызовет x.toLowerCase, используя отражение, и обернет результат в новый динамический экземпляр.

_select_ вызывается для любого метода без аргументов, тогда как _invoke_ вызывается для любого метода с аргументами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...