基类应仅管理通用属性(颜色、填充、名称)并声明抽象方法(面积、周长、绘制),子类专注自身特有字段与具体实现;避免在基类中耦合坐标、画布等非图形本体职责,确保可扩展性与运行时多态。
用继承实现图形编辑器的基类抽象,核心是提取共性、预留差异、保证可扩展。最常用写法不是堆砌功能,而是抓住“所有图形都有的东西”和“每个图形必须自己算的东西”这两头。
明确基类该管什么
基类只负责图形通用属性和强制接口,不参与具体计算:
- 颜色、是否填充、名称这些状态,统一用私有字段 + public getter 管理
- 面积、周长、绘制逻辑这些因图而异的行为,声明为 abstract 方法,强制子类实现
- 像 displayInfo 这类组合输出的方法,可以在基类写好框架,调用抽象方法,子类无需重写就能用
子类只专注自身特性
Circle 和 Rectangle 不需要重复定义颜色或填充状态,它们只做三件事:
- 继承基类(Java 用 extends,C# 用 :,C++ 用 : public Base)
- 添加自己独有的字段:比如 Circle 加 radius,Rectangle 加 width 和 height
- 覆写抽象方法:getArea() 里写 π×r²,getPerimeter() 里写 2πr;另一个类就写长×宽和 2×(长+宽)
避免常见设计陷阱
初学者容易把基类写成“大杂烩”,结果反而难维护:
- 别在 Shape 里存坐标(x/y)或画布引用——那是编辑器层该管的,不是图形本体的职责
- 别让基类实现 toString() 或 draw() 的具体逻辑,除非它只是拼接通用字段(如 name + color),否则应留给子类决定怎么展示
- 如果将来要加三角形、椭圆,现有结构不用改基类,只要新增子类并实现那两个抽象方法就行
运行时多态才是关键价值
编辑器真正用起来时,不会写 Circle c = new Circle(...),而是:
- 用 Shape[] shapes = {new Circle(...), new Rectangle(...)}
- 遍历调用 shapes[i].getArea() —— 具体执行哪个版本,由实际对象类型决定
- 这样增删图形类型,编辑器主逻辑完全不用动,只换数组内容即可










