问题描述
我最近看到了几个 Scala 问题(例如 这里、这里和这里) 要求使用代理,而且在我自己的工作中不止一次出现.Scala 库有许多代理特征(如果我没记错的话,有 14 个).
I've seen several Scala questions recently (e.g. here, here, and here) that called for the use of proxies, and it's come up more than once in my own work. The Scala library has a number of proxy traits (14, if I counted correctly).
代理类/特征通常包含很多样板:
Proxy classes/traits usually contain lots of boilerplate:
class FooProxy(val self: Foo) extends Foo {
// added behavior
def mymethod = ...
// forwarding methods
def method1 = self.method1
def method2(arg: String) = self.method2(arg)
...
}
trait Foo {
def method1: Unit
def method2(arg: String): Unit
}
我的第一个想法是定义一个 Proxy[T]
特征,可以如下使用:
My first thought was to define a Proxy[T]
trait that could be used as follows:
class FooProxy(val self: Foo) extends Proxy[Foo] {
// added behavior
def mymethod = ...
}
其中 trait Proxy[T] 扩展了 T
.当然,如果没有编译器魔法,实际上是不可能定义 Proxy
特征的.
where trait Proxy[T] extends T
. Of course, it's not actually possible to define the Proxy
trait without compiler magic.
我的下一个想法是寻找一个编译器插件(这样的功能显然不在现有的编译器中,或者这 14 个代理特征的来源会小得多).果然,我找到了Kevin Wright 的 AutoProxy 插件.该插件旨在巧妙地解决代理问题,以及其他用例(包括动态混合):
My next thought was to look for a compiler plugin (such a capability clearly isn't in the existing compiler, or the sources for those 14 proxy traits would be much smaller). Sure enough, I found Kevin Wright's AutoProxy plugin. The plugin is intended to solve the proxy issue neatly, along with other use cases (including dynamic mixins):
class FooProxy(@proxy val self: Foo) { ... }
不幸的是,它的工作似乎在 11 月(2009 年)停滞不前.所以,我的问题是
Unfortunately, it looks like work on it stalled in November (2009). So, my questions are
- 是否有关于 AutoProxy 插件的继续工作?
- 这会进入编译器吗?
- 是否正在考虑其他方法?
- 最后,这是否表明了 Scala 的一个显着弱点?毕竟,在给定 lisp 风格的宏的情况下,难道不能定义
Proxy
特征吗?
推荐答案
四个问题,四个答案
我是,但家庭必须放在第一位!此外,其他人也参与了在编译器插件中合成方法的一般问题的研究.
I am, though family has to come first! Plus others are involved in looking at the general issue with synthesizing methods in a compiler plugin.
如果是这样,它很可能是不同的形式,可能没有使用注释.
If so, it will most likely be in a different form, perhaps without using annotations.
我不知道任何等效的插件,尽管 Scala GSOC 候选项目之一部分基于我的自动代理代码.然而,有一个非常干净的解决方案可以在大多数情况下工作,并且根本不需要编译器插件:您定义一个从 FooProxy 到 Foo 的隐式转换,它只返回 self
成员;这将使您大部分时间到达那里.该方法的主要问题是,如果您需要使用 Java 代码,它会使生活变得更加困难,它在速度/内存方面的效率可能较低,这是您必须注意的另一个隐含因素.
I don't know of any equivalent plugins, although one of the Scala GSOC candidate projects was based partly on my autoproxy code. There is, however, one very clean solution that will work in most cases and doesn't need a compiler plugin at all: You define an implicit conversion from FooProxy to Foo that simply returns the self
member; this will get you most of the way there. The main issues with the approach are that it'll make life harder if you need to use your code from Java, it may be less efficient in terms of speed/memory, and it's another imlicit that you have to be aware of.
令人沮丧的部分是编译器中几乎所有必要的逻辑都已经可用,而且它用于混入,所以确实应该是一种处理任务的优雅方式.
The frustrating part is that almost all of the necessary logic is already available in the compiler, and it's used for mixins, so there really should be an elegant way of handling the task.
这篇关于Scala 中的代理/委托的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!