我知道这是一个基本问题,但是我找不到关于此的其他StackOverflow帖子或任何好的API文档。

假设我有一个类似于Appliance的抽象类,然后有一些诸如ToasterBlender的类扩展了Appliance。现在,假设我想创建一个包含混合元素的ArrayList,这些元素最终都是Appliance的成员,但也可以是ToasterBlenderBlender类具有一个称为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对象上实现的方法正试图在碰巧是ApplianceBlender对象上执行,但是编译器没有意识到这一点。

我试图用ArrayList规范中的<Appliance>替换<? extends Appliance>类型,但这会带来其他错误,并且将不再编译。

什么是基于抽象类型创建列表,然后通过使用诸如getClassName()之类的方法来调用子类类型的方法来检索子类类型的正确方法?

添加了

由于很多人立即指出了一个明显的事实:更好地使用继承,所以我需要解释一下。对于这个项目,我们必须假设Appliance的所有子类都是由第三方创建的,并放入了一些我们无法更改的包中。这是以一种糟糕,繁琐的方式完成的,其中所有不同的子类都有不同的开/关方法,并且无法更改。因此,设计平滑的Appliance抽象类的选项对我来说并不开放。例如,Toaster的方法为startToasting(),而Oven的方法为heatUp(),每种方法均用作两个不同类的“on”方法。

我认为该练习旨在教会我们:您将如何对他人的不良设计工作进行改造,以最大程度地减少 future 的损失。

最佳答案

使用 instanceof getClass ,而不要滚动自己的getClassName,然后对您刚刚确定的类型进行显式转换。

就是说,最好使用@guitarflow的答案,尽管如果存在不能仅传递给switchOff方法的状态,则该方法可能不起作用。

09-25 20:22