Как преодолеть проблему со стиранием типов для реализации посетителем - PullRequest
5 голосов
/ 29 декабря 2010

Я начинаю работать с 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 ]

2 голосов
/ 30 января 2011

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

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

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

Приветствия

0 голосов
/ 29 декабря 2010

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

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){

    }
}

}

0 голосов
/ 29 декабря 2010

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

...