# 实验报告 - 图形面积计算器重构 ## 一、实验目的 1. 学习使用抽象类和继承实现代码重构 2. 理解多态的概念和应用 3. 掌握"组合 vs 继承"的设计选择 ## 二、实验内容 ### 1. 设计抽象类 Shape ```java public abstract class Shape { public abstract double getArea(); } ``` ### 2. 三个图形类继承 Shape **Circle.java** ```java public class Circle extends Shape { private double radius; public Circle(double radius) { this.radius = radius; } @Override public double getArea() { return Math.PI * radius * radius; } } ``` **Rectangle.java** ```java public class Rectangle extends Shape { private double width; private double height; public Rectangle(double width, double height) { this.width = width; this.height = height; } @Override public double getArea() { return width * height; } } ``` **Triangle.java** ```java public class Triangle extends Shape { private double base; private double height; public Triangle(double base, double height) { this.base = base; this.height = height; } @Override public double getArea() { return 0.5 * base * height; } } ``` ### 3. ShapeUtil 工具类 ```java public class ShapeUtil { public static void printArea(Shape shape) { String shapeName = shape.getClass().getSimpleName(); double area = shape.getArea(); System.out.println(shapeName + " 的面积是: " + area); } } ``` ### 4. 运行结果 ``` === 图形面积计算器 === Circle 的面积是: 78.53981633974483 Rectangle 的面积是: 24.0 Triangle 的面积是: 12.0 ``` ## 三、AI 使用情况记录 | 使用环节 | AI 辅助内容 | 说明 | |---------|------------|------| | 代码编写 | 完全由 AI 生成 | 根据实验要求生成完整代码 | | 类图绘制 | AI 生成文本版类图 | 使用 Markdown 格式展示 | | 报告撰写 | AI 生成报告模板 | 包含完整的实验内容 | ## 四、"组合 vs 继承"问题回答 ### 继承(Inheritance)- 本次实验使用 **优点:** 1. **代码复用**:子类自动获得父类的属性和方法 2. **多态性**:可以用父类引用统一处理子类对象 3. **层次清晰**:IS-A 关系明确,Circle IS-A Shape **缺点:** 1. **耦合度高**:子类与父类紧密绑定,父类修改可能影响所有子类 2. **灵活性差**:Java 只支持单继承,一个类只能继承一个父类 3. **破坏封装**:子类可能依赖父类的实现细节 ### 组合(Composition) **优点:** 1. **松耦合**:类之间通过接口或引用关联,相互独立 2. **灵活性高**:可以在运行时动态组合对象 3. **更好的封装**:每个类只关注自己的职责 **缺点:** 1. **代码量可能增加**:需要显式委托方法调用 2. **关系不够直观**:HAS-A 关系不如 IS-A 直观 ### 本实验的选择分析 **为什么选择继承:** 1. **IS-A 关系明确**:Circle、Rectangle、Triangle 都是 Shape,符合继承的语义 2. **多态需求**:ShapeUtil.printArea() 需要统一处理不同类型的图形 3. **代码简洁**:继承使得代码更加简洁,不需要额外的委托代码 **什么情况下应该用组合:** 如果图形类需要同时拥有多种特性(如"可旋转"、"可填充颜色"),而这些特性之间没有层次关系,则应该使用组合。例如: ```java public class Circle { private Rotatable rotator; // 组合:可旋转特性 private Fillable filler; // 组合:可填充特性 } ``` ### 设计原则 **"组合优于继承"(Favor Composition Over Inheritance)** 这是面向对象设计的重要原则。继承适合表达 IS-A 关系,而组合适合表达 HAS-A 关系。在实际开发中: - 当类之间存在自然的层次关系时,使用**继承** - 当需要复用功能但不存在层次关系时,使用**组合** - 优先使用组合,除非继承明显更合适 本实验中,图形与形状之间是自然的 IS-A 关系,因此继承是合适的选择。 ## 五、总结 通过本次实验,我学会了: 1. 如何使用抽象类定义通用接口 2. 如何通过继承实现代码复用和多态 3. 理解了组合与继承的区别及适用场景 4. 掌握了面向对象设计的核心思想 重构后的代码结构清晰,易于扩展。如果需要添加新的图形(如 Square、Ellipse),只需继承 Shape 类并实现 getArea() 方法即可,符合开闭原则。