среда, 27 мая 2009 г.

И вновь про двойную диспетчеризацию на Java

Пусть надо реализовать функцию от двух переменных f(X, Y), где типы X и Y - суть корни деревьев наследования, причем так, чтобы при появлении нового типа X или Y компилятор нам сам подсказывал, что надо дописать. Обычная стандартная задача двойной диспетчеризации :) Не претендуя на всеобщий ее охват, напишу примененный мною метод реализации такого механизма. Добавлю только, что типы X и Y абстрактные.

Итак, в типе

Определяю новый тип (interface) YVisitor:
public interface YVisitor
{
void visitY1( Y1 y );
void visitY2( Y1 y );
}
помещаю туда методы про те потомки типа Y, которые вспоминаются.

В тип Y помещаю абстрактный метод:
public abstract void visit( X x );

Тип X делаю implements YVisitor и добавляю метод

public void f( Y y )
{
y.visit( this );
}

В каждом потомке типа Y нужно теперь реализовать метод visit. Делаем это по такой схеме, для примера на классе Y1:
class Y1 extends Y
{
...
public void visit(X x)
{
x.visitY1(this);
}
}
Очень важный момент, что суффикс имени вызываемого метода должен содержать имя класса (потомка Y)! Если такого метода нет в классе X (а это означает, что еще нет соотв.visit-метода в интерфейсе), то идем в интерфейс YVisitor и добавляем метод void visitY1(Y1 y1); Таким образом, при добавлении нового потомка типа Y такая схема работы позволит отследить весь необходимый новый код.

Кроме того, компилятор будет требовать реализации методов visitYi в каждом потомке типа X. Если появится новый потомок типа X, компилятор сообщит, что в нем нужно реализовать все visitYi.

Вызвать это дело следует так: x.f(y), где x типа X, y типа Y.

1 комментарий:

  1. Этот комментарий был удален администратором блога.

    ОтветитьУдалить