如何在Any对象上使用applyDynamic

ib8*_*b84 1 scala dynamic

我正在考虑使用新的Type Dynamic,但发现一个明显的用例没有得到很好的实现.我正在尝试为面向对象的数据库创建便利包装器.它遭受了转换和可用性问题,因为它序列化和反序列化对象(它的方法返回Object).

第一个问题:我的数据库的get方法反序列化A类型的对象.Althought A有一个方法a(),我可能知道在给定的时刻,我有一个A,我不能调用a(),因为java只看到对象.如果"底层"对象实际上具有该方法,那么动态机制会为我设置,还是我必须自己在applyDynamic中处理它?我在REPL中尝试过,似乎对我没那么做.如果我必须自己检查,最简单的方法是什么(使用scala的新反射),检查该对象是否具有方法"methodname",如果是,则调用它.

害怕这个/sf/answers/773948731/ 我回到java的反射,它非常容易地执行方法调用部分.

我想出来了:

 scala> import java.lang.reflect.Method
 import java.lang.reflect.Method

 scala> class DynTest3 extends Dynamic {
 | def pee():String = "yuppie"
 |   def execSucced(method: Method, args: Any*):Boolean = return try{method.invoke(args); true} catch { case e: Exception => false }
 | def applyDynamic(methodName : String)(args: Any*){
 |     val succed = classOf[DynTest3].getDeclaredMethods.filter(m => m.getName() == methodName).exists(m => execSucced(m))
 | if (!succed)
 | throw new java.lang.NoSuchMethodException
 | }
 | }
 defined class DynTest3
Run Code Online (Sandbox Code Playgroud)

但:

 scala> val y: Object = new DynTest3
 y: Object = DynTest3@74c74b55

 scala> y.asInstanceOf[Dynamic].pee()
 <console>:11: error: value applyDynamic is not a member of Dynamic
          y.asInstanceOf[Dynamic].pee()
Run Code Online (Sandbox Code Playgroud)

所以基本上,这不起作用,即使我转向动态.Casting to Dynamic已经使整个事情变得毫无用处,因为我想让用户免于投射.但也许有人可以创建一个隐式转换any2Dynamic ...

任何提示?

Eug*_*ako 6

DynamicScala中的一个简单的编译时重写方案.详细信息在SIP-17:Type Dynamic中提供,在这里我将尝试用不同的词语解释它们.

与C#不同,C#dynamic引入了元对象的整个基础结构,绑定器和调用点缓存+实现了一个mini-C#编译器,在运行时为服务重载提供服务,在Scala中我们决定采用最简单的方法.

我已经提到了编译时重写,现在是时候详细说明了.有几个规则,但让我们来看看最重要的规则.

如果我们无法编译foo.bar(arg1 ... argN),并且foo的静态类型是Dynamic的子类型,则将调用重写为foo.applyDynamic("bar")(arg1 .. argN).重写的表达式将像往常一样进行类型检查,就好像它是由程序员手动编写的一样.

在你的情况下y.asInstanceOf[Dynamic].pee(),调用的接收者y.asInstanceOf [Dynamic]肯定是一个子类型为Dynamic的静态类型,因此触发了重写.重写的结果是y.asInstanceOf[Dynamic].applyDynamic("pee")().但是,当Scala尝试对此表达式进行类型检查时,它会失败,因为Dynamic只是一个空标记特征,它没有定义任何方法.

要解决这个问题,你会转换为子类型Dynamic并拥有applyDynamic成员的东西(或者你没有强制转换,但是让你的API返回而不是Object,但是那个东西).您可以自己编写这些内容,也可以使用DynamicProxy(子类化以包含您的自定义逻辑),我希望它将包含在2.10.0-M5中.