Как преодолеть проблему со стиранием типов для реализации посетителем

Я начинаю работать с Java после некоторых проектов на C# и C++.

Я хотел спроектировать интерфейсы посетителей следующим образом:

public interface ActionVisitor<A> {
    void visitAction(A action);    
}

public interface MySmallActionVisitor 
extends ActionVisitor<ActionA>,
    ActionVisitor<ActionB>
{

}

public interface MyFullActionVisitor 
extends ActionVisitor<ActionA>,
    ActionVisitor<ActionB>,ActionVisitor<ActionC>,ActionVisitor<ActionD> //....
{

}

Конечно, это не работает из-за стирания типа. (Причина, по которой я хочу что-то подобное, заключается в том, что у меня будут разные интерфейсы Visitor для разных групп действий, которые можно посетить.)

Единственное решение, которое приходит мне в голову - это объявить интерфейсы.

public interface ActionAVisitor {
        void visitAction(ActionA action);    
    }
public interface ActionBVisitor {
        void visitAction(ActionB action);    
    }
//...

а потом

public interface MySmallActionVisitor 
extends ActionAVisitor, ActionBVisitor
{

}

Это бы сработало, но мне не хотелось бы объявлять все интерфейсы ActionXVisitor, что является глупым повторением и множеством файлов...

У вас есть идеи, как сделать это лучше?

Большое спасибо!

3 ответа

Решение

Я работаю с большой и сложной библиотекой в ​​Java, которая широко использует шаблон посетителя очень чистым и аккуратным способом. В частности, я столкнулся с той же проблемой стирания типов, и теперь она решена.

Если у вас есть шанс, посмотрите статью, которую я написал об этом.

Это длинная статья, которая подробно объясняет концепцию шаблона Visitor, а в последней части статьи обсуждается пример из реальной жизни, который включает полиморфизм и стирание типов.

ура

Я бы использовал один непараметризованный интерфейс посетителя, а затем внутри метода посетителя выполнял бы диспетчеризацию по типу.

Нет способа избежать экземпляра внутри метода. Но вы можете сделать это более изящным:

public interface MarkerInterface{}

public interface ActionVisitor<T extends MarkerInterface> {
void visitAction(T action);}

public class A implements MarkerInterface{}

public class B implements MarkerInterface{}

public class MySmallActionVisitor implements ActionVisitor<MarkerInterface>{

@Override
public void visitAction(MarkerInterface action) {
    if(action instanceof A){

    }
    else if(action instanceof B){

    }
}

}

Другие вопросы по тегам