我试图了解多态性,以及通过子类和超类进行继承时的最佳实践。我有三节课:项目,书籍和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>;
这难道不会击败多态性吗?此外,假设我现在想打印所有项目的列表,则必须调用两个数组列表,而不是仅包含所有数组的列表。
感谢您的帮助,如有需要,我可以提供更详细的代码示例。
答案 0 :(得分:0)
如果return url_for("home")
确实是DVD专用的,则强制转换是唯一的方法。您将需要在每次需要的时候进行投射。
强制转换之前,好的做法是(使用instanceof)检查类型,或捕获getRuntime
。
但更优雅的方法可能是拥有DVD列表而不是项目列表。如果需要,您还可以列出项目清单。
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
上声明getRuntime()
并在Book中编写一个实现,该实现的确会返回Item
的实例,什么都没有。