Вызов универсального интерфейса 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);