我知道这是一个基本问题,但是我找不到关于此的其他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
对象上执行,但是编译器没有意识到这一点。我试图用ArrayList规范中的
<Appliance>
替换<? extends Appliance>
类型,但这会带来其他错误,并且将不再编译。什么是基于抽象类型创建列表,然后通过使用诸如
getClassName()
之类的方法来调用子类类型的方法来检索子类类型的正确方法?添加了
由于很多人立即指出了一个明显的事实:更好地使用继承,所以我需要解释一下。对于这个项目,我们必须假设
Appliance
的所有子类都是由第三方创建的,并放入了一些我们无法更改的包中。这是以一种糟糕,繁琐的方式完成的,其中所有不同的子类都有不同的开/关方法,并且无法更改。因此,设计平滑的Appliance
抽象类的选项对我来说并不开放。例如,Toaster
的方法为startToasting()
,而Oven
的方法为heatUp()
,每种方法均用作两个不同类的“on”方法。我认为该练习旨在教会我们:您将如何对他人的不良设计工作进行改造,以最大程度地减少 future 的损失。
最佳答案
使用 instanceof
或 getClass
,而不要滚动自己的getClassName
,然后对您刚刚确定的类型进行显式转换。
就是说,最好使用@guitarflow的答案,尽管如果存在不能仅传递给switchOff
方法的状态,则该方法可能不起作用。