Java ArrayList由一个抽象类和任何扩展它的东西组成?
我知道这是一个基本问题,但我找不到其他StackOverflow帖子或任何关于这个的好API文档 假设我有一个抽象类,比如Java ArrayList由一个抽象类和任何扩展它的东西组成?,java,arraylist,Java,Arraylist,我知道这是一个基本问题,但我找不到其他StackOverflow帖子或任何关于这个的好API文档 假设我有一个抽象类,比如Appliance,然后我有一些类,比如Toaster和Blender,它们扩展了Appliance。现在假设我想创建一个包含混合元素的ArrayList,所有这些元素最终都是Appliance的成员,但也可以是Toaster或Blender。Blender类有一个名为turnBlenderOff()的方法,Toaster类有一个名为turnToasterOff()的方法,我
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));
}
}
}
我看到,这个方法只在Blender
对象上实现,它试图在一个Appliance
对象上执行,而这个对象恰好是Blender
,但编译器没有意识到这一点
我尝试将
类型替换为使用或,而不是滚动您自己的getClassName
,然后对您刚刚识别的类型执行显式转换
也就是说,我们更喜欢@guitarflow的答案,尽管如果存在不能直接传递到关闭方法的状态,那么这种方法可能不起作用。如果您想使用一个抽象类,并且所有子类实际上都有相同的函数,为什么不在抽象基类中使用一个名为“turnDeviceOff”的函数呢并相应地在子类中重写它。这就是面向对象的方法。数组列表还可以
但你可以这样做:
public abstract class Appliance{
//declare an abstract method
abstract void switchOff();
}
然后
对于其他子类,也可以这样做
最后,
for(Appliance element: yourList){
element.switchOff();
}
您完全违背了继承的观点:Appliance
应该定义一个turnOff()
方法,它的子对象应该根据自己的需要适当地实现该方法。这样,您就可以只使用设备的列表
s,而不必担心什么是什么
否则,他们首先扩展设备
有什么意义
如果您确实需要找出某种类型的东西,请使用instanceof
,将类名作为字符串进行测试是一种非常脆弱的方法
编辑
随机风格提示:几乎不再需要在List
s上使用索引访问:
public PowerPoint(List<Appliance> initialList){
for(Appliance app : initialList)
applianceList.add(app);
}
编辑2
更直接的翻译:
public void switchOff(){
for(Appliance app : applianceList)
switchOff(app);
}
private void switchOff(Appliance app){
if(app instanceof Blender)
turnBlenderOff(app);
else if(app instanceof Toaster)
turnToasterOff(app);
else if(app instanceof Oven)
turnOvenOff(app);
else
throw new RuntimeException("unknown appliance: " + app);
}
您还可以在规范化API的不同设备类周围添加一个包装器,但这可能不值得(取决于涉及的程度)。有两种方法可以做到这一点。第一种(也是不太推荐的)方法是使用instanceof关键字并将您的设备实例转换为混合器实例:
for(Appliance a : list){
if(a instanceof Blender) this.turnBlenderOff((Blender)a);
...
}
这是不好的,因为instanceof速度很慢,并且不允许您利用Java最强大的多态性对应项后期绑定。更好的方法是让Appliance类有一个名为turnOff()的抽象公共方法。然后你可以做一些类似的事情:
for(Appliance a : list){
a.turnOff();
...
}
正确的解决方法是在Appliance类中添加turnOff()
方法,并让不同的子类适当地重写它们。如果您这样做,那么大的“If”代码就会消失。MygetClassName()
只是基本对象方法getSimpleName()
…对象没有getSimpleName
方法的包装。你的意思是getClass().getSimpleName()
?是的,我的意思是class
。我的synatx有:Toaster.class.getSimpleName()
用于Toaster
子类,例如.Ah。我仍然不相信这比就在那里做更好;如果(appliance.getClass()==Toaster.class)
,我会做一些类似的事情。我想你是对的。将此与Ben Lawry的答案结合起来,给出了一个很好的解决方案。这就是我在下面写的代码。这就是路!不幸的是,这一选择没有得到考虑。在我的项目中,我们必须假设,烤面包机
,搅拌机
等都来自某个第三方软件包,都是由不同的人实现的,并且都有自己粗糙、不同的开/关方法。这是练习要点的一部分。@EMS也是第三方软件包中的设备吗?是的。这是第三方抽象类。好的,然后我会比较类或类的名称。尽管您的示例将解释和使用接口或抽象基类!可以为第三方类添加方法吗?请参阅我对Kent答案的评论。请参阅我对Kent答案的评论。
public void switchOff(){
for(Appliance app : applianceList)
switchOff(app);
}
private void switchOff(Appliance app){
if(app instanceof Blender)
turnBlenderOff(app);
else if(app instanceof Toaster)
turnToasterOff(app);
else if(app instanceof Oven)
turnOvenOff(app);
else
throw new RuntimeException("unknown appliance: " + app);
}
for(Appliance a : list){
if(a instanceof Blender) this.turnBlenderOff((Blender)a);
...
}
for(Appliance a : list){
a.turnOff();
...
}