Вызов универсального интерфейса Java с абстрактным параметром

Я знаю, что есть много подобных вопросов, но мне не повезло найти хорошее и чистое решение, если это вообще возможно. Я реализую универсальный интерфейс с подклассами абстрактного типа. Проблема в том, что когда я их вызываю, я должен либо выполнять приведение типа в switch/case, либо приведение типа в каждом методе внутри реализации интерфейса, и я не могу придумать хороший и чистый подход... Я лучше просто напишу вниз короткий пример.

// An abstract type with 2 implementations...
public abstract class ObjTypeAbstract {}

public class ObjType extends ObjTypeAbstract {}
public class ScriptType extends ObjTypeAbstract {}

Теперь процессор для обоих типов с интерфейсом

interface ProcessorInterface<T extends ObjTypeAbstract> {
    public void abcMethod(T obj);
}

public class ObjProcessor implements ProcessorInterface<ObjType> {
    public void abcMethod(ObjType obj) {}
}
public class ScriptProcessor implements ProcessorInterface<ScriptType> {
    public void abcMethod(ScriptType obj) {}
}

То, с чем я борюсь, - это способ вызова этих процессоров на основе ObjAbstractType. У меня есть один класс, что серверы в качестве промежуточного программного обеспечения?? или как мне это назвать.

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

public class Processor {
    private ProcessorInterface objProcessor = new ObjProcessor();
    private ProcessorInterface scriptProcessor = new ScriptProcessor();

    public methodAbc(ObjAbstractType obj) {
        getProcessor(obj).abcMethod(obj);
    }

    private ProcessorInterface getProcessor(ObjAbstractType obj) {
        if (obj instanceof ObjType) {
            return objectProcessor;
        } else if (obj instanceof ScriptType) {
            return scriptProcessor;
        }

        return nullProcessor;
    }
}

Это то, что я хотел бы иметь, это также заботится о приведении типа objAbstract к фактическому типу для abcMethod, проблема в том, что это приводит к предупреждению RawType, которое не нарушает код, но я хотел бы избавиться от Это.

И вот где я застрял... потому что, если я приведу процессоры к определенному типу, как это:

private ProcessorInterface<ObjType> objProcessor = new ObjProcessor();
private ProcessorInterface<ScriptType> scriptProcessor = new ScriptProcessor();

Я не смогу вернуть абстрактный метод из метода getProcessor, поэтому мне пришлось бы реализовать эти интерфейсы с ObjAbstractType со всеми его методами и иметь приведение типов во всех методах каждого процессора, например:

public class ScriptProcessor implements ProcessorInterface<ObjAbstractType> {
    public void abcMethod(ObjAbstractType obj) {
        ScriptType scr = (ScriptType) obj;
    }
}

Другое решение может заключаться в том, чтобы иметь переключатель / регистр внутри класса промежуточного программного обеспечения процессора и приводить к нему ObjAbstractType, но мне нужно было бы написать этот переключатель внутри abcMethod и всех остальных или из метода getProcessor, который возвращает и Processor, и приведенный ObjType... так что я Придется вернуть некоторые dto, содержащие оба.:/

Есть ли у вас какие-либо идеи / шаблоны, которые могут помочь мне избавиться от предупреждения о вызовах RawType, не расширяя код большим количеством приведений типа switch/case или type? Желаю тебе хорошего дня, и я буду рад любой дискуссии, Дэвид.

2 ответа

Решение

Вам нужен способ сохранить отображение между ObjTypeAbstract класс и ProcessorInterface пример.
Вы могли бы использовать Map что ассоциирует ObjTypeAbstractс (как ключ) к ProcessorInterfaceс (как значение).
О проблеме необработанного типа, вы можете использовать ProcessorInterface<? extends ObjTypeAbstract> для объявленной переменной, но вам все равно нужно будет выполнить небезопасное приведение к ProcessorInterface<ObjTypeAbstract> быть в состоянии призвать ProcessorInterface.abcMethod() с параметром а ObjTypeAbstract объявленный тип.
Этот акт неизбежен с вашим реальным дизайном.

Это может дать что-то вроде:

public class Processor {

    private Map<Class<? extends ObjTypeAbstract>, ProcessorInterface<? extends ObjTypeAbstract >> map = new HashMap<>();

    public Processor(){
        map.put(ObjType.class, new ObjProcessor());
        map.put(ScriptType.class, new ScriptProcessor());   
    }
    public void methodAbc(ObjTypeAbstract obj) {
        @SuppressWarnings("unchecked")
        ProcessorInterface<ObjTypeAbstract> processorInterface = (ProcessorInterface<ObjTypeAbstract>) map.get(obj.getClass());
        processorInterface.abcMethod(obj);
    }

}

Я не думаю, что есть более элегантный способ обойти какую-то форму instanceof логика. Тем не менее, нет необходимости в приведении, если вы добавляете некоторые типы в getProcessor,

    public <T extends ObjTypeAbstract> ProcessorInterface<T> getProcessor(Class<T> theClass) {
        if (theClass.isAssignableFrom(ObjType.class)) {
            return objProcessor;
        } else if (theClass.isAssignableFrom(ScriptType.class)) {
            return scriptProcessor;
        }
        return null;
    }

Это можно затем назвать так:

    ProcessorInterface<ScriptType> scriptProcessor = new Processor().getProcessor(ScriptType.class);
    ProcessorInterface<ObjType> objProcessor = new Processor().getProcessor(ObjType.class);
Другие вопросы по тегам