1

我正在考虑使用新的动态类型,但发现一个明显的用例没有很好地实现。我正在尝试为面向对象的数据库创建方便的包装器。它存在转换和可用性问题,因为它序列化和反序列化对象(它的方法返回对象)。

第一个问题:我的数据库的 get 方法反序列化了 A 类型的对象。虽然 A 有一个方法 a(),而且我可能知道在给定的时刻,我有一个 A,但我不能调用 a(),因为 java只看到对象。如果“基础”对象实际上具有该方法,动态机制是否会为我尝试,还是我必须自己在 applyDynamic 中处理它?我在 REPL 中尝试过,似乎对我没有这样做。如果我必须自己检查,最简单的方法是什么(是否使用 scala 的新反射)来检查该对象是否具有方法“方法名”,如果是则调用它。

被这个https://stackoverflow.com/a/11056410/703862吓到了, 我回退到 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

但:

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

所以基本上,这不起作用,即使我转换为动态。投射到动态已经会使整个事情变得无用,因为我想使用户免于投射。但也许可以创建一个隐式转换 any2Dynamic ...

有什么提示吗?

4

1 回答 1

6

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

与在 C# 中dynamic引入元对象、绑定器和调用站点缓存的整个基础架构 + 实现了一个 mini-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 只是一个空的标记特征,它没有定义任何方法。

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

于 2012-07-03T08:11:51.423 回答