Scala сквозные обертки

Очень часто я хочу "заменить" один метод данного объекта.

foo: Foo
foo.bar(i) // original
foo.baz(s) // replace this implementation

Я закончу создание сквозного класса-обёртки.

class FooWrapper(foo: Foo) extends Foo {
  def bar(i: Int) = foo.bar(i)
  def baz(s: String) = foo.baz(s)
}

А потом

foo: Foo
val foo2 = new FooWrapper(foo) { def baz(s: String) = ... }
foo2.bar(i)
foo2.baz(s)

Это работает с чертами и классами и работает без изменения исходного кода типа.

Я использую это совсем немного, особенно при адаптации библиотек или других фрагментов кода.

Это может стать утомительным с множеством методов. На днях я хотел заменить shutdown метод на ExecutorService Например, и я должен был сделать это для дюжины методов.

Это распространенная идиома, или это обычно делается по-другому? Я подозреваю, что это можно сделать с помощью макроса, хотя я не нашел ни одного из существующих, которые бы это делали.

1 ответ

Решение

Вы можете достичь этого с помощью AOP (Аспектно-ориентированное программирование)

Для этого есть много библиотек, попробуйте эту - https://github.com/adamw/scala-macro-aop

  • Обратите внимание, что эта библиотека сейчас находится в стадии POC, поэтому вы можете искать что-то более зрелое. Я поместил это здесь, потому что я думаю, что это показывает концепцию очень ясно.

Для вашего примера вам нужно сделать что-то вроде

class FooWrapper(@delegate wrapped: Foo) extends Foo {
  def baz(i: Int) = ???
}
Другие вопросы по тегам