2 changed files with 309 additions and 0 deletions
@ -0,0 +1,236 @@ |
|||||
|
# 图形面积计算器重构 - 实验报告 |
||||
|
|
||||
|
## 一、实验概述 |
||||
|
|
||||
|
### 实验目的 |
||||
|
通过重构图形面积计算器,理解面向对象编程中的抽象类、继承和多态概念,比较组合与继承的优缺点。 |
||||
|
|
||||
|
### 实验背景 |
||||
|
原有 Circle、Rectangle、Triangle 类独立存在,无法统一处理。通过引入抽象类 Shape,实现代码的统一管理和复用。 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 二、AI使用情况记录 |
||||
|
|
||||
|
### 1. AI协助项目创建 |
||||
|
- **创建项目结构**:通过 Trae IDE 环境快速创建项目目录 |
||||
|
- **文件生成**:使用代码生成工具创建 6 个 Java 类文件 |
||||
|
- **编译运行**:使用终端工具编译和测试程序 |
||||
|
|
||||
|
### 2. AI代码协助 |
||||
|
- **抽象类设计**:协助设计 Shape 抽象类,包含抽象方法 getArea() |
||||
|
- **继承关系**:实现 Circle、Rectangle、Triangle 继承 Shape |
||||
|
- **多态实现**:设计 ShapeUtil 的 printArea() 方法 |
||||
|
- **类图绘制**:生成 UML 类图描述 |
||||
|
|
||||
|
### 3. AI功能总结 |
||||
|
| 功能 | 使用情况 | |
||||
|
|------|---------| |
||||
|
| 文件创建 | ✅ 自动创建 7 个文件 | |
||||
|
| 代码生成 | ✅ 生成完整 Java 代码 | |
||||
|
| 编译运行 | ✅ 自动编译和测试 | |
||||
|
| 文档生成 | ✅ 生成类图和报告 | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 三、核心设计思路 |
||||
|
|
||||
|
### 1. 抽象类 Shape 的设计 |
||||
|
**为什么使用抽象类**: |
||||
|
- 定义统一接口:所有图形都有 getArea() 方法 |
||||
|
- 强制子类实现:抽象方法确保每个图形都必须计算面积 |
||||
|
- 代码复用:共享 name 属性和 getName() 方法 |
||||
|
|
||||
|
```java |
||||
|
public abstract class Shape { |
||||
|
private String name; |
||||
|
|
||||
|
public Shape(String name) { |
||||
|
this.name = name; |
||||
|
} |
||||
|
|
||||
|
public abstract double getArea(); |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### 2. 继承关系设计 |
||||
|
**Circle、Rectangle、Triangle 继承 Shape**: |
||||
|
- **is-a 关系**:圆是一种图形,矩形是一种图形,三角形是一种图形 |
||||
|
- **复用代码**:继承 name 属性,无需重复定义 |
||||
|
- **实现多态**:每个图形按自己的方式计算面积 |
||||
|
|
||||
|
### 3. 多态的应用 |
||||
|
**ShapeUtil.printArea(Shape shape)**: |
||||
|
- 参数是 Shape 类型 |
||||
|
- 可以接受 Circle、Rectangle、Triangle 任何子类 |
||||
|
- 自动调用对应子类的 getArea() 方法 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 四、组合 vs 继承 |
||||
|
|
||||
|
### 问题:组合 vs 继承,什么时候用哪个? |
||||
|
|
||||
|
### 1. 继承(Inheritance) |
||||
|
|
||||
|
**是什么**: |
||||
|
- 类与类之间的 is-a 关系 |
||||
|
- 子类继承父类的属性和方法 |
||||
|
- 用 extends 关键字实现 |
||||
|
|
||||
|
**本项目使用继承的原因**: |
||||
|
```java |
||||
|
// 继承关系:圆 是一种 图形 |
||||
|
Circle extends Shape |
||||
|
|
||||
|
// 继承关系:矩形 是一种 图形 |
||||
|
Rectangle extends Shape |
||||
|
|
||||
|
// 继承关系:三角形 是一种 图形 |
||||
|
Triangle extends Shape |
||||
|
``` |
||||
|
|
||||
|
**继承的优点**: |
||||
|
✅ 代码复用:子类自动拥有父类的属性和方法 |
||||
|
✅ 多态性:可以用父类类型统一处理子类 |
||||
|
✅ 符合自然逻辑:圆确实是一种图形 |
||||
|
|
||||
|
**继承的缺点**: |
||||
|
❌ 耦合度高:父类改变会影响所有子类 |
||||
|
❌ 破坏封装:子类可以访问父类的 protected 成员 |
||||
|
❌ 不灵活:继承关系在编译时确定,运行时无法改变 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 2. 组合(Composition) |
||||
|
|
||||
|
**是什么**: |
||||
|
- 类与类之间的 has-a 关系 |
||||
|
- 一个类包含另一个类的对象作为成员 |
||||
|
- 用成员变量实现 |
||||
|
|
||||
|
**组合的例子**: |
||||
|
```java |
||||
|
// 组合关系:汽车 有一个 引擎 |
||||
|
public class Car { |
||||
|
private Engine engine; // 组合 |
||||
|
|
||||
|
public Car() { |
||||
|
this.engine = new Engine(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class Engine { |
||||
|
// 引擎的功能 |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
**组合的优点**: |
||||
|
✅ 低耦合:类之间相对独立 |
||||
|
✅ 灵活性:运行时可以替换组合的对象 |
||||
|
✅ 符合设计原则:优先使用组合而非继承 |
||||
|
|
||||
|
**组合的缺点**: |
||||
|
❌ 代码较多:需要显式调用组合对象的方法 |
||||
|
❌ 不能直接复用:无法自动继承功能 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 3. 选择原则:什么时候用继承,什么时候用组合? |
||||
|
|
||||
|
| 场景 | 推荐使用 | 原因 | |
||||
|
|------|----------|------| |
||||
|
| **is-a 关系**(是一种) | 继承 | 圆是一种图形,符合继承逻辑 | |
||||
|
| **has-a 关系**(有一个) | 组合 | 汽车有一个引擎,使用组合 | |
||||
|
| **需要代码复用** | 继承 | 子类可以复用父类代码 | |
||||
|
| **需要灵活性** | 组合 | 运行时可以动态改变 | |
||||
|
| **需要多态** | 继承 | 父类引用指向子类对象 | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 4. 本项目为什么选择继承? |
||||
|
|
||||
|
**分析**: |
||||
|
1. **is-a 关系明确**: |
||||
|
- 圆 是一种 图形 ✅ |
||||
|
- 矩形 是一种 图形 ✅ |
||||
|
- 三角形 是一种 图形 ✅ |
||||
|
|
||||
|
2. **需要多态**: |
||||
|
- ShapeUtil.printArea(Shape shape) 需要统一处理 |
||||
|
- 用 Shape 类型可以接受任何图形 |
||||
|
|
||||
|
3. **代码复用**: |
||||
|
- 所有图形都有 name 属性 |
||||
|
- 继承避免重复代码 |
||||
|
|
||||
|
**如果用组合会怎样?** |
||||
|
```java |
||||
|
// 不推荐的组合方式 |
||||
|
public class Circle { |
||||
|
private Shape shape; // 组合 |
||||
|
|
||||
|
public Circle() { |
||||
|
this.shape = new Shape("圆"); |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
这样就失去了多态的优势,不适合本项目。 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 五、实验总结 |
||||
|
|
||||
|
### 1. 完成的工作 |
||||
|
✅ 创建抽象类 Shape,包含抽象方法 getArea() |
||||
|
✅ 让三个图形继承 Shape,实现面积计算 |
||||
|
✅ 编写 ShapeUtil,提供 printArea() 方法 |
||||
|
✅ 绘制完整的 UML 类图 |
||||
|
✅ 完成实验报告,记录 AI 使用情况 |
||||
|
✅ 回答"组合 vs 继承"问题 |
||||
|
|
||||
|
### 2. 学到的知识点 |
||||
|
- 抽象类的定义和使用 |
||||
|
- 继承关系的实现 |
||||
|
- 多态的实际应用 |
||||
|
- 组合与继承的对比 |
||||
|
- 面向对象设计原则 |
||||
|
|
||||
|
### 3. 代码验证结果 |
||||
|
程序运行成功,输出: |
||||
|
``` |
||||
|
========== 图形面积计算器测试 ========== |
||||
|
--- 圆形测试 --- |
||||
|
图形名称: 圆 |
||||
|
面积: 78.53981633974483 |
||||
|
---------------------- |
||||
|
--- 矩形测试 --- |
||||
|
图形名称: 矩形 |
||||
|
面积: 24.0 |
||||
|
---------------------- |
||||
|
--- 三角形测试 --- |
||||
|
图形名称: 三角形 |
||||
|
面积: 20.0 |
||||
|
---------------------- |
||||
|
========== 测试完成 ========== |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 六、反思 |
||||
|
|
||||
|
### 1. 继承的使用场景 |
||||
|
通过本次实验,我深刻理解了继承的适用场景: |
||||
|
- 当存在明确的 is-a 关系时 |
||||
|
- 当需要多态性时 |
||||
|
- 当需要代码复用时 |
||||
|
|
||||
|
### 2. 设计原则的重要性 |
||||
|
"优先使用组合而非继承"是重要的设计原则,但不是绝对的。关键是根据具体场景选择合适的方式。 |
||||
|
|
||||
|
### 3. AI 工具的价值 |
||||
|
AI 工具在代码生成、项目搭建、文档编写等方面大大提高了效率,但核心的设计思路和概念理解还需要自己掌握。 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
**实验完成日期**:2026年3月28日 |
||||
@ -0,0 +1,73 @@ |
|||||
|
# 图形面积计算器 - 类图 |
||||
|
|
||||
|
## UML类图(文字描述) |
||||
|
|
||||
|
``` |
||||
|
┌─────────────────────────┐ |
||||
|
│ <<abstract>> │ |
||||
|
│ Shape │ |
||||
|
├───────────────────────┤ |
||||
|
│ - name: String │ |
||||
|
├───────────────────────┤ |
||||
|
│ + Shape(name: String)│ |
||||
|
│ + getName(): String │ |
||||
|
│ + getArea(): double │ |
||||
|
│ <<abstract>> │ |
||||
|
└───────────┬───────────┘ |
||||
|
│ |
||||
|
┌──────────────────────┼──────────────────────┐ |
||||
|
│ │ │ |
||||
|
▼ ▼ ▼ |
||||
|
┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐ |
||||
|
│ Circle │ │ Rectangle │ │ Triangle │ |
||||
|
├───────────────────┤ ├───────────────────┤ ├───────────────────┤ |
||||
|
│ - radius: double │ │ - width: double │ │ - base: double │ |
||||
|
│ │ │ - height: double │ │ - height: double │ |
||||
|
├───────────────────┤ ├───────────────────┤ ├───────────────────┤ |
||||
|
│ + Circle(radius) │ │ + Rectangle(w,h) │ │ + Triangle(b,h)│ |
||||
|
│ + getRadius() │ │ + getWidth() │ │ + getBase() │ |
||||
|
│ + setRadius() │ │ + setWidth() │ │ + setBase() │ |
||||
|
│ + getArea() │ │ + getHeight() │ │ + getHeight() │ |
||||
|
│ @Override │ │ + setHeight() │ │ + setHeight() │ |
||||
|
└───────────────────┘ │ + getArea() │ │ + getArea() │ |
||||
|
│ @Override │ │ @Override │ |
||||
|
└───────────────────┘ └───────────────────┘ |
||||
|
|
||||
|
┌─────────────────────────────────┐ |
||||
|
│ ShapeUtil │ |
||||
|
├─────────────────────────────────┤ |
||||
|
│ + printArea(Shape shape) │ |
||||
|
└─────────────────────────────────┘ |
||||
|
``` |
||||
|
|
||||
|
## 类图说明 |
||||
|
|
||||
|
### 类关系说明 |
||||
|
|
||||
|
1. **Shape(抽象类) |
||||
|
- 是所有图形的父类 |
||||
|
- 包含抽象方法 getArea() |
||||
|
- 所有子类必须实现此方法 |
||||
|
|
||||
|
2. **Circle(圆) |
||||
|
- 继承自 Shape |
||||
|
- 实现圆形面积计算:π × r² |
||||
|
|
||||
|
3. **Rectangle(矩形) |
||||
|
- 继承自 Shape |
||||
|
- 实现矩形面积计算:宽 × 高 |
||||
|
|
||||
|
4. **Triangle(三角形) |
||||
|
- 继承自 Shape |
||||
|
- 实现三角形面积计算:0.5 × 底 × 高 |
||||
|
|
||||
|
5. **ShapeUtil(工具类) |
||||
|
- 提供静态方法 printArea() |
||||
|
- 参数为 Shape 类型(多态) |
||||
|
- 可以接受任何 Shape 的子类 |
||||
|
|
||||
|
### 继承关系符号 |
||||
|
- 箭头表示继承关系(is-a) |
||||
|
- Circle is-a Shape |
||||
|
- Rectangle is-a Shape |
||||
|
- Triangle is-a Shape |
||||
Loading…
Reference in new issue