2010-08-13 38 views
16

我最近见过几个Scala问题(例如herehere和),这些问题需要使用代理,并且在我自己的工作中不止一次出现。斯卡拉图书馆有一些代理性状(14,如果我正确计算)。Scala的代理/代表

代理类/性状通常含有大量的样板:

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]特点,可以作如下用途:

class FooProxy(val self: Foo) extends Proxy[Foo] { 
    // added behavior 
    def mymethod = ... 
} 

其中trait Proxy[T] extends T。当然,如果没有编译器的魔力,定义Proxy特征实际上是不可能的。

我的下一个念头,就是找一个编译器插件(这种能力显然不是在现有的编译器,或为那些14个代理特质的来源会小得多)。果然,我发现Kevin Wright's AutoProxy plugin。该插件是为了整齐地解决了代理发行,与其他使用案例(包括动态混入)沿:

class FooProxy(@proxy val self: Foo) { ... } 

不幸的是,它看起来像它的工作在(2009年)十一月停滞不前。所以,我的问题是

  1. 是否有继续工作的AutoProxy插件?
  2. 这会找到它的方式进入编译器?
  3. 是否正在考虑其他方法?
  4. 最后,这是否意味着斯卡拉的一个重大缺陷?毕竟,难道不可能为给定lisp风格的宏定义一个Proxy特性?
+0

特征不能有参数。你建议他们加入吗?此外,您还没有显示任何无法通过添加隐式转换来解决的问题。建立隐式转换的提议是不必要的样板吗? – 2010-08-13 19:05:37

+0

“性状不能有参数”:愚蠢的错误,修正。 – 2010-08-13 19:33:59

+0

隐式转换解决了类似的问题,但它们并不总是合适的(否则为什么EPFL的人在Scala库中包含这么多的代理?)。首先,他们比代表团招致更多的开销。其次,广泛使用隐式转换会伤害可维护性/可读性。 – 2010-08-13 20:02:37

回答

6

四个问题,四个答案

  1. 我,虽然家有先来!另外其他人也参与了在编译器插件中综合方法的一般问题。

  2. 如果是的话,它很可能会以不同的形式,也许没有使用注释。

  3. 我不知道任何等效的插件,虽然斯卡拉GSOC候选项目之一,是对我的自动代理的代码部分基于。然而,有一个非常干净的解决方案可以在大多数情况下工作,根本不需要编译器插件:您可以定义从FooProxy到Foo的隐式转换,它仅返回self成员;这会让你获得大部分途径。这种方法的主要问题是,如果您需要使用Java代码,它会让生活更加艰难,速度/内存方面的效率可能会低一些,而且您必须了解另一种方法。

  4. 令人沮丧的是,几乎所有必需的逻辑已经在编译器中可用,并且它用于混入,所以确实应该是是处理任务的优雅方式。

+0

查看Groovy中的@Delegate AST转换。这太好了。 http://docs.codehaus.org/display/GROOVY/Delegate+transformation – sourcedelica 2011-04-29 18:21:27

5

亚当Warski recently bloggeda Macro-based approach可以在斯卡拉2.11的工作,肯定在斯卡拉2.10微距天堂编译器插件的工作原理。

这个库可以让你写

class FooProxy(@delegate wrapped: Foo) extends Foo { 
    // added behavior 
    def mymethod = ... 

    // forwarding methods (generated for you) 
    // def method1 = wrapped.method1 
    // def method2(arg: String) = wrapped.method2(arg) 
} 

该项目是在一个非常早期的,在写这篇文章的时间段,所以谨慎的概念证明型是必要的。