Scala 如何在任何对象上使用applyDynamic
我正在考虑使用新类型的Dynamic,但发现一个明显的用例没有得到很好的实现。我正在尝试为面向对象数据库创建方便的包装器。它面临强制转换和可用性问题,因为它序列化和反序列化对象(它的方法返回对象) 第一个问题: 我的数据库的get方法反序列化了一个类型为A的对象。虽然A有一个方法A(),而且我可能在给定的时刻知道,我有一个A,但我不能调用A(),因为java只看到对象。如果“底层”对象真的有这种方法,动态机制会为我尝试吗?还是我必须自己在applyDynamic中处理这种方法?我在REPL中试过了,但对我来说似乎不行。 如果我必须自己检查,最简单的方法是什么(使用scala的新反射还是不使用),来检查该对象是否有方法“methodname”,如果是,则调用它 被这个吓跑了 我回到java的反射,它可以很容易地完成方法调用部分 我想到了这个:Scala 如何在任何对象上使用applyDynamic,scala,dynamic,Scala,Dynamic,我正在考虑使用新类型的Dynamic,但发现一个明显的用例没有得到很好的实现。我正在尝试为面向对象数据库创建方便的包装器。它面临强制转换和可用性问题,因为它序列化和反序列化对象(它的方法返回对象) 第一个问题: 我的数据库的get方法反序列化了一个类型为A的对象。虽然A有一个方法A(),而且我可能在给定的时刻知道,我有一个A,但我不能调用A(),因为java只看到对象。如果“底层”对象真的有这种方法,动态机制会为我尝试吗?还是我必须自己在applyDynamic中处理这种方法?我在REPL中试过
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
但是:
scala>valy:Object=new DynTest3
y:对象=DynTest3@74c74b55
scala>y.asInstanceOf[Dynamic].pee()
:11:错误:值applyDynamic不是Dynamic的成员
y、 asInstanceOf[Dynamic].pee()
所以基本上,这不起作用,即使我将其转换为Dynamic。强制转换为Dynamic已经会使整个事情变得毫无用处,因为我想从强制转换中拯救用户。但也许可以创建一个隐式转换any2Dynamic
任何提示?Scala中的动态是一种简单的编译时重写方案。详细内容在中提供,在这里,我将尝试用不同的语言解释它们 与C#中的
dynamic
引入了元对象的整个基础结构不同,Binder和callsite caching+实现了一个迷你C#编译器,在运行时为重载提供服务,在Scala中,我们决定使用尽可能简单的方法
我已经提到了编译时重写,现在是详细说明的时候了。有几个规则,但让我们来看一看最重要的规则。
如果我们无法编译foo.bar(arg1…argN),并且foo的静态类型是Dynamic的子类型,那么将调用重写为foo.applyDynamic(“bar”)(arg1…argN)。重写的表达式将像往常一样进行类型检查,就好像它是由程序员手动编写的一样
对于y.asInstanceOf[Dynamic].pee()
,调用的接收方y.asInstanceOf[Dynamic]肯定是一个静态类型,属于动态子类型,因此会触发重写。重写的结果是y.asInstanceOf[Dynamic].applyDynamic(“pee”)()
。然而,当Scala尝试对这个表达式进行类型检查时,它失败了,因为Dynamic只是一个空的标记特征,它没有定义任何方法
要解决这个问题,您可以强制转换为动态子类型并具有applyDynamic成员的对象(或者您不强制转换,但使API返回的不是Object,而是该对象)。您可以自己编写,也可以使用DynamicProxy(子类化以合并自定义逻辑),我希望它将包含在2.10.0-M5中。Scala中的Dynamic是一种简单的编译时重写方案。详细内容在中提供,在这里,我将尝试用不同的语言解释它们 与C#中的
dynamic
引入了元对象的整个基础结构不同,Binder和callsite caching+实现了一个迷你C#编译器,在运行时为重载提供服务,在Scala中,我们决定使用尽可能简单的方法
我已经提到了编译时重写,现在是详细说明的时候了。有几个规则,但让我们来看一看最重要的规则。
如果我们无法编译foo.bar(arg1…argN),并且foo的静态类型是Dynamic的子类型,那么将调用重写为foo.applyDynamic(“bar”)(arg1…argN)。重写的表达式将像往常一样进行类型检查,就好像它是由程序员手动编写的一样
对于y.asInstanceOf[Dynamic].pee()
,调用的接收方y.asInstanceOf[Dynamic]肯定是一个静态类型,属于动态子类型,因此会触发重写。重写的结果是y.asInstanceOf[Dynamic].applyDynamic(“pee”)()
。然而,当Scala尝试对这个表达式进行类型检查时,它失败了,因为Dynamic只是一个空的标记特征,它没有定义任何方法
要解决这个问题,您可以强制转换为动态子类型并具有applyDynamic成员的对象(或者您不强制转换,但使API返回的不是Object,而是该对象)。您可以自己编写这个东西,也可以使用DynamicProxy(子类化以合并您的自定义逻辑),我希望它将包含在2.10.0-M5中。这似乎与-我认为
DynamicProxy
是您要找的东西。根据正在设计Scala 2.10宏的Eugene Burmako的说法,该代理目前不可用,但可能在某个时候(希望在2.10决赛中)再次可用,感谢SCIS。同一页上被接受的答案已经很有用了。我会检查一下,但是我在intellij上又遇到了一些问题,代码示例在REPL中无法正常工作。代理就在那里。Chris Hodapp做得很好,从头开始重新创建了代理:.@ib84。如果代码示例在REPL中不起作用,请告诉我,我会解决您的问题。我的电子邮件在个人资料中。它似乎与-我认为DynamicProxy
是你要找的东西。根据正在设计Scala 2.10宏的Eugene Burmako的说法,该代理目前不可用,但可能在某个时候(希望在2.10决赛中)再次可用,感谢SCIS。同一页上被接受的答案已经很有用了。我会检查一下,但我在intellij上又遇到了一些问题,代码示例无法正常工作
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()