Я знаю, что это основной вопрос, но я не могу найти другие посты StackOverflow или какие-либо хорошие документы по API по этому вопросу.
Скажем, у меня есть абстрактный класс, такой как Appliance
, а затем у меня есть несколько классовкак Toaster
и Blender
, которые расширяются Appliance
.Теперь предположим, что я хочу создать ArrayList, который будет содержать смешанные элементы, которые в конечном итоге являются членами Appliance
, но также могут быть Toaster
или Blender
.Класс Blender
имеет метод с именем turnBlenderOff()
, а класс Toaster
имеет метод с именем turnToasterOff()
, и я захочу перебрать мой ArrayList и вызвать эти методы в зависимости от того, к какому подклассу фактически принадлежит элемент.
В настоящее время я создаю класс с именем PowerPoint
и пытаюсь:
// Constructor given an ArrayList of appliances.
public PowerPoint(ArrayList<Appliance> initial_list_of_appliances){
int listSize = initial_list_of_appliances.size();
for(int ii = 0; ii < listSize; ii++){
this.applianceList.add(initial_list_of_appliances.get(ii));
}
}
/////
// Method to switch everything in the list OFF simultaneously.
/////
public void switchOff(){
int N = this.applianceList.size();
String cur_name;
for(int ii = 0; ii < N; ii++){
cur_name = this.applianceList.get(ii).getClassName();
if(cur_name.equals("Blender")){
this.turnBlenderOff(this.applianceList.get(ii));
}
else if(cur_name.equals("Toaster")){
this.turnToasterOff(this.applianceList.get(ii));
}
else if(cur_name.equals("Oven")){
this.turnOvenOff(this.applianceList.get(ii));
}
}
}
Большая часть моего кода компилируется нормально, но я продолжаю получать это сообщение об ошибке:
PowerPoint.java:83: turnBlenderOff(appliances.ApplianceWrapper.Blender) in PowerPoint cannot be applied to (appliances.ApplianceWrapper.Appliance)
this.turnBlenderOff(this.applianceList.get(ii));
Я вижу, что этот метод, реализованный для работы только с Blender
объектами, пытается быть выполнен на Appliance
объекте, который оказывается Blender
, но компилятор этого не понимает.
Я пытался заменить тип <Appliance>
на <? extends Appliance>
в спецификациях ArrayList, но это дало дополнительные ошибки и больше не компилировалось.
Как правильно составить список на основе абстрактного типа, но затем вызывать методы подклассного типа, используя что-то вроде getClassName()
для извлечения типа подкласса?
Added
Поскольку многие люди сразу указалиочевидное: лучше использовать наследование, мне нужно объяснить.Для этого проекта мы должны предположить, что все подклассы Appliance
были созданы сторонними разработчиками и помещены в некоторый пакет, который мы не можем изменить.Это было сделано нехорошо, так как все разные подклассы имеют разные методы включения / выключения, и это нельзя изменить.Таким образом, возможность создания гладкого Appliance
абстрактного класса мне не открыта.Например, Toaster
имеет метод startToasting()
, а Oven
имеет метод heatUp()
, каждый из которых служит методом «on» для двух разных классов.
Я думаю, что упражнениепредназначено для того, чтобы научить нас: как вы могли бы подстроить чужую плохую дизайнерскую работу, чтобы минимизировать будущий ущерб.