Прокси / делегаты в Скала - PullRequest
18 голосов
/ 13 августа 2010

Недавно я видел несколько вопросов по Scala (например, здесь , здесь и здесь ), которые требовали использования прокси, и он возникне раз в моей работе.В библиотеке Scala есть ряд прокси-черт (14, если я правильно сосчитал).

Прокси-классы / черты обычно содержат множество шаблонов:

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 черт прокси было бы намного меньше).Конечно же, я нашел плагин Кевина Райта AutoProxy .Плагин предназначен для аккуратного решения проблемы с прокси, наряду с другими вариантами использования (включая динамические миксины):

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

К сожалению, похоже, что работа над ним остановилась в ноябре (2009).Итак, мои вопросы

  1. Продолжается ли работа над плагином AutoProxy?
  2. Будет ли это найти путь к компилятору?
  3. Рассматриваются ли другие подходы??
  4. Наконец, указывает ли это на существенную слабость в Scala?В конце концов, нельзя ли определить черту Proxy с помощью макросов в стиле lisp?

Ответы [ 2 ]

8 голосов
/ 18 августа 2010

Четыре вопроса, четыре ответа

  1. Да, хотя семья должна стоять на первом месте!Кроме того, другие занимаются рассмотрением общей проблемы синтеза методов в плагине компилятора.

  2. Если это так, то, скорее всего, он будет в другой форме, возможно, без использования аннотаций.

  3. Я не знаю ни одного эквивалентного плагина, хотя один из кандидатов на проекты Scala GSOC был частично основан на моем коде авто-прокси.Однако есть одно очень чистое решение, которое будет работать в большинстве случаев и вообще не нуждается в плагине компилятора: вы определяете неявное преобразование из FooProxy в Foo, которое просто возвращает член self;это даст вам большую часть пути туда.Основные проблемы, связанные с этим подходом, заключаются в том, что он усложнит жизнь, если вам потребуется использовать свой код из Java, он может быть менее эффективным с точки зрения скорости / памяти, и это еще одно косвенное, о котором вам следует знать.

  4. Огорчает то, что почти вся необходимая логика уже доступна в компиляторе, и она используется для миксинов, поэтому на самом деле должен быть элегантным способом обработкизадание.

6 голосов
/ 21 сентября 2013

Адам Варски недавно написал в блоге о подходе на основе макросов , который может работать в Scala 2.11 и определенно работает с плагином компилятора Macro Paradise в Scala 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)
}

Проект находится на очень ранней стадии разработки, на момент написания этой статьи, поэтому необходима осторожность.

...