Как преодолеть проблему со стиранием типов для реализации посетителем
Я начинаю работать с 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){
}
}
}