Недавно я видел несколько вопросов по 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 = ...
}
где черта Proxy [T] расширяет T
. Конечно, фактически невозможно определить черту Proxy
без магии компилятора.
Моя следующая мысль состояла в том, чтобы искать плагин компилятора (такой возможности явно нет в существующем компиляторе или источники для этих 14 признаков прокси были бы намного меньше). Конечно же, я нашел плагин Кевина Райта AutoProxy . Плагин предназначен для аккуратного решения проблемы с прокси, наряду с другими вариантами использования (включая динамические миксины):
class FooProxy(@proxy val self: Foo) { ... }
К сожалению, похоже, что работа над ним остановилась в ноябре (2009). Итак, мои вопросы:
Proxy
с помощью макросов в стиле lisp? Четыре вопроса, четыре ответа
Да, но семья должна быть на первом месте! Кроме того, другие участвуют в рассмотрении общей проблемы с синтезированием методов в плагине компилятора.
Если так, то, скорее всего, он будет в другой форме, возможно, без использования аннотаций.
Я не знаю никаких эквивалентных плагинов, хотя один из проектов-кандидатов Scala GSOC был частично основан на моем коде автопрокси. Однако есть одно очень чистое решение, которое будет работать в большинстве случаев и совсем не требует подключаемого модуля компилятора: вы определяете неявное преобразование из FooProxy в Foo, которое просто возвращает член self
; это поможет вам в большинстве случаев. Основные проблемы с этим подходом заключаются в том, что он усложнит жизнь, если вам нужно использовать свой код из Java, он может быть менее эффективным с точки зрения скорости / памяти, и это еще одно неявное, о котором вы должны знать.
Раздражает то, что почти вся необходимая логика уже доступна в компиляторе и используется для миксинов, так что действительно должен быть элегантный способ решения задачи.