无法在初始化为超类的 ArrayList 中调用派生类的方法

Posted

技术标签:

【中文标题】无法在初始化为超类的 ArrayList 中调用派生类的方法【英文标题】:Unable to call derived class's method in ArrayList initialized to super class 【发布时间】:2019-05-21 15:10:24 【问题描述】:

我正在通过 Java 学习面向对象的编程,并正在编写一个冰箱程序来练习。在我的程序中,有两个派生类 PerishableItem 和 LeftoverItem 的类 Item。我创建了一个初始化为 Item 的 ArrayList,并向 ArrayList 添加了一个 PerishableItem 和一个 LeftoverItem。问题是我无法调用派生类中不在 Item 类中的方法。

ArrayList<Item> itms = new ArrayList<Item>();

itms.add(new Item("apple", 0.45, new Date(1, 1, 2001)));
itms.add(new LeftoverItem("rice", 9.99, new Date(1, 1, 2001), 3));
itms.add(new PerishableItem("yogurt", 4.48, new Date(1, 1, 2001), 5));

System.out.println(itms.get(2).getDaysToExpire()); // error here

getDaysToExpire() 是 PerishableItem 类中的方法,而不是 Item 类中的方法。似乎编译器甚至根本看不到该方法。谢谢!

【问题讨论】:

方法是private吗? itms.get(2) 将返回一个Item 类型的对象(因为该列表被声明为ArrayList&lt;Item&gt;)。如果getDaysToExpire() 不是Item 上的方法,那么这就是编译器使其失败的原因。 您可以在 Item 类中使用 getDaysToExpire() 方法。如果您有特定于子类的内容,则可以在派生类 LeftoverItem、PerishableItem 中覆盖 getDaysToExpire() 方法。 【参考方案1】:

Item 还应该有 getDaysToExpire() 方法才能工作...但是当您调用它们时,派生类中的正确 getDaysToExpire() 将被调度。

另一种方法是将items.get(2) 类型转换为PerishableItem,然后调用getDaysToExpire,但这绝对不是一个好的设计。

冰箱里的任何物品都会有一个有效期,所以,我不明白为什么 Item 类中也没有这个方法。

【讨论】:

出于好奇,为什么将 items.get() 类型转换为 PerishableItem 不好?感谢您的建议! @JustinLam 在很多中,让我们举一个简单的情况.. 如果您进行类型转换,那么除了 PerishableItem 之外,您不能在 items[2] 中放置任何其他对象。另外,假设您从冰箱中删除了“米饭”,那么 Yogurt 将成为 items(1)...您可以使用反射来解决此问题,但正确的解决方案是简洁且定义明确的继承。

以上是关于无法在初始化为超类的 ArrayList 中调用派生类的方法的主要内容,如果未能解决你的问题,请参考以下文章

指定初始化程序缺少对超类的指定初始化程序的超级调用

Swift:“必须调用超类的指定初始化程序”错误,即使代码正在这样做

ArrayList 包含同一个超类的不同对象 - 如何访问子类的方法

JavaSE复习_3 继承

8- 类

类的属性