
本文介绍如何通过继承与多态机制,将不同子类(Lindt、Baravelli、ChocoAmor)的糖果盒对象统一存入父类类型 ArrayList,并正确打印其内容——关键在于合理设计类结构、重写 toString() 方法,并避免语法与逻辑错误。
本文介绍如何通过继承与多态机制,将不同子类(lindt、baravelli、chocoamor)的糖果盒对象统一存入父类类型 `arraylist
要实现一个能容纳多种具体糖果盒(如 Lindt、Baravelli、ChocoAmor)的 CandyBag,核心思路是利用面向对象的多态性:所有子类均继承自抽象或具体父类 CandyBox,而 CandyBag 仅持有一个 List<candybox></candybox>,无需关心具体子类类型。
首先,修正原始代码中的几处关键问题:
-
CandyBag不应继承CandyBox—— 礼盒(CandyBag)与单个糖果盒(CandyBox)是“组合”(has-a)关系,而非“继承”(is-a)关系。错误继承会导致语义混乱和设计缺陷。 - 实例变量(如
candybag)不能在类体中直接执行操作(如new Lindt(...)、add(...)),必须放在构造器或方法内。 -
printArray方法参数不应是candybag(变量名非法作类型),而应是List<candybox></candybox>或直接操作成员变量;且循环中item类型为CandyBox,不可用String声明。 - 所有子类需重写
toString(),否则默认打印内存地址(如Lindt@1b6d3586),无法体现业务信息。
✅ 正确实现如下:
// 父类:所有糖果盒的通用基类
class CandyBox {
protected String flavor;
protected String origin;
public CandyBox(String flavor, String origin) {
this.flavor = flavor;
this.origin = origin;
}
// 建议提供基础 toString,子类可选择覆盖
@Override
public String toString() {
return String.format("CandyBox[flavor=%s, origin=%s]", flavor, origin);
}
}
// 子类示例:Lindt(含 height, width)
class Lindt extends CandyBox {
private double height, width;
public Lindt(String flavor, String origin, double height, double width) {
super(flavor, origin);
this.height = height;
this.width = width;
}
@Override
public String toString() {
return String.format("Lindt[%s, %s, h=%.1f, w=%.1f]", flavor, origin, height, width);
}
}
// 子类示例:Baravelli
class Baravelli extends CandyBox {
private double height, width;
public Baravelli(String flavor, String origin, double height, double width) {
super(flavor, origin);
this.height = height;
this.width = width;
}
@Override
public String toString() {
return String.format("Baravelli[%s, %s, h=%.1f, w=%.1f]", flavor, origin, height, width);
}
}
// 子类示例:ChocoAmor(注意原题拼写为 ChocoAmor,非 ChocAmor)
class ChocoAmor extends CandyBox {
private double weight; // 示例:用 weight 替代单一参数
public ChocoAmor(String flavor, String origin, double weight) {
super(flavor, origin);
this.weight = weight;
}
@Override
public String toString() {
return String.format("ChocoAmor[%s, %s, weight=%.1fg]", flavor, origin, weight);
}
}
// 礼盒类:组合多个 CandyBox,不继承!
class CandyBag {
private List<candybox> candyBag = new ArrayList();
// 构造器中初始化三种糖果盒
public CandyBag() {
candyBag.add(new Lindt("Cherry", "Austria", 20.0, 5.4));
candyBag.add(new Baravelli("Grape", "Italy", 6.7, 8.7));
candyBag.add(new ChocoAmor("Coffee", "France", 5.5));
}
// 打印全部糖果盒(利用多态自动调用各子类 toString)
public void printContents() {
System.out.println("=== CandyBag Contents ===");
for (CandyBox item : candyBag) {
System.out.println(item); // 自动触发对应子类的 toString()
}
}
// 可选:提供访问内部列表的方法(如需外部操作)
public List<candybox> getContents() {
return Collections.unmodifiableList(candyBag);
}
}</candybox></candybox>
在 main 方法中使用:
public class Main {
public static void main(String[] args) {
CandyBag gift = new CandyBag();
gift.printContents();
}
}
输出示例:
=== CandyBag Contents === Lindt[Cherry, Austria, h=20.0, w=5.4] Baravelli[Grape, Italy, h=6.7, w=8.7] ChocoAmor[Coffee, France, weight=5.5g]
? 关键注意事项:
- ✅ 始终用
CandyBox类型引用子类对象,体现多态本质; - ✅ 每个子类必须重写
toString(),返回有意义的字符串表示; - ❌ 避免在类定义体中执行实例化与
add()操作(编译报错); - ❌ 不要让
CandyBag继承CandyBox——这是典型的“组合优于继承”原则实践; - ? 若需防止外部修改内部列表,使用
Collections.unmodifiableList()封装 getter 返回值。
通过以上设计,你不仅能正确填充并打印混合类型的糖果盒列表,还构建了可扩展、易维护、符合 OOP 原则的代码结构。










