Типизированный посетитель получает вызов от неправильных типов - PullRequest
0 голосов
/ 23 июня 2019

Я использую общий абстрактный класс фреймворка AbstractProcessor<T extends CtElement>, который в основном является посетителем, который посещает все элементы T. Существует метод

public void process(T element)

, который действует на все элементы указанного типа ичто-то делает.

Затем у меня есть конкретные реализации этого класса AbstractProcessor, которые я создаю, используя своего рода фабричный шаблон, держа список общего супертипа AbstractProcessor, чтобы затем вызвать process -методчерез полиморфизм на них.Один из этих конкретных классов может быть чем-то вроде XYZProcessor<T extends CtElement> extends AbstractProcessor<T>.

. Теперь я создаю эти конкретные процессоры, такие как new XYZProcessor<CtNamedElement>(), где CtNamedElement является подтипом CtElement, поэтому process -методXYZProcessor вызывается только с CTNamedElements.Но process -метод, кажется, вызывается для всех посещаемых элементов типа CtElement, а НЕ только для элементов типа CtNamedElement, как я хочу.

Кто-нибудь знает, что здесь происходит?

РЕДАКТИРОВАТЬ: соответствующий код:

создание таких процессоров

case CLASS:
 //CtClass is subtype of CtNamedElement
 this.setProcessor(new AnnotatedWithProcessor<CtClass>(targetName, attributeMappings, metapackage));
break;

Определение класса:

public class AnnotatedWithProcessor<T extends CtNamedElement> extends AbstractProcessor<T> {
    @Override
    public void process(T element) {
     //do stuff here with elements of correct type
    }

А затем вызывать процессоры следующим образом:

//this gets set with a concrete case like above
AbstractProcessor<?> processor;
...
//this astModel gets processed with the respective processor,
//where I expect the process method only getting called for the correct types (in this case only when coming over elements of type CtClass),
//but the method gets called for all types of CtNamedElement, not only for those of type CtClass
this.astModel.processWith(processor);

1 Ответ

0 голосов
/ 23 июня 2019

Похоже, что вы делаете такое незаконное приведение где-то, но трудно сказать, не видя больше вашей реализации.Кто звонит XYZProcessor::process?Почему вы ожидаете, что определение универсального интерфейса будет выполнять какую-либо фильтрацию?

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

private final Map<Class, Object> processorMap = new HashMap<Class, Object>();

public <T extends CtElement> void putProcessor(
    Class<T> elementClass, 
    AbstractProcessor<? extends T> processor
) {
     processorMap.put(elementClass, processor);
}

@SuppressWarnings("unchecked")
public <T extends CtElement> AbstractProcessor<? extends T> getProcessor(
    Class<T> elementClass,
) {
    return (AbstractProcessor<? extends T>) processorMap.get(elementClass);
}

Теперь, когда вы ищете процессор, вы можете использовать эту карту, чтобы найти правильнуюреализация для вызова:

public void <T extends CtElement> process(T element) {
    getProcessor(element.getClass()).process(element);
}

Вы можете расширить это, чтобы разрешить несколько реализаций для каждого класса, или отфильтровать processorMap для всех допустимых процессоров для element.getClass(), используя Class::isInstance, а затем обрабатывать для каждогодействительный ключ.

...