我试图理解多态性,以及通过子类和超类继承工作时的最佳实践。我有三个课程:项目,书籍和DVD。 Items是超类,Books和DVD是扩展Items的子类。
首先,我尝试将类型为Book和DVD的新对象存储在类型为Items的数组列表中,这些工作正常。
ArrayList<Items> library = new ArrayList<Items>;
library.add(new DVD(...));
library.add(new Book(...));
当我尝试从DVD子类调用方法getRuntime时出现问题。这将返回DVD的运行长度。我不能将此方法移动到Items超类,它不适用于书籍。
library.get(0).getRuntime();
我可以理解为什么会出现错误,数组列表中的对象存储了Items类型,并且只能访问Items类中的方法。因此,一种选择是转换为正确的子类类型:
((DVD) library.get(0)).getRuntime();
但是,如果我从子类中调用许多方法,我每次都必须进行转换吗?另外,使用这样的演员是不好的做法?
我的另一个选择是为每个子类创建两个单独的数组列表:
ArrayList<DVD> libraryDvds = new ArrayList<DVD>;
ArrayList<Books> libraryBooks = new ArrayList<Books>;
这不会破坏多态性的观点吗?此外,假设我现在想要打印所有项目的列表,我必须调用两个数组列表而不是只保存所有项目列表。
感谢您的帮助,如果需要,我可以提供更详细的代码示例。
如果getRuntime
真的特定于DVD那么演员是唯一的方法。你需要每次都需要施放。在施法之前,好的做法是先检查类型(使用instanceof),或者抓住ClassCastException
。
但更优雅的方式可能是拥有DVD列表而不是项目列表。如果需要,您还可以拥有一个项目列表。
ArrayList<Items> library = new ArrayList<Items>; // list to use when processing the whole library
ArrayList<DVD> libraryDvds = new ArrayList<DVD>; // list to use when processing only DVDs
我不认为你是通过这样做来打败多态性的,因为你只是为DVD做了特定的动作,所以你想要实现的功能不是多态的。
最后一个解决方案,如果你真的想在这里使用多态,那就是在getRuntime()
上声明Item
并在Book中编写一个实现,它会返回一个什么都不做的Runtime
实例。