📄 一句话概括
拿到一个类有三招——拿来就用(调方法)、装进去用(组合 has-a)、继承着用(is-a);三招覆盖绝大多数设计。
📝 本节和前面几节的关系
图纸与成品分清了,最后一问:拿到一个类,能拿它干什么?答案恰好三种。
一、用法 1:拿来就用
把类当工具箱:直接调它的方法或常量,如数学工具、日期格式化——MathBox.round2(x) 用完即走。 特点是无状态、零负担:不建对象或建了随手扔,适合【纯功能】的场景。 各类语言的工具类库(Java 的 Math、Python 的 math 模块函数)都是这一路的产物。
二、用法 2:装进去用(组合)
一个类的字段里装另一个类的对象——Car 里装一台 Engine,关系是【有】(has-a)。 这正是 7.3 拼装观的正式机制:组件拼大件,用的就是组合。 组合的好处:Engine 可以单独开发、单独升级、单独测试——Car 毫无察觉。
三、用法 3:继承着用
子类继承父类再扩展——SportsCar 是一种 Car(is-a),白得 start() 再加 turbo()。 适合【真的是一种】的场景:概念上确实存在家族关系,且子类要沿袭父类的接口合同。 【⚠️ 2026 现状】三招的使用心法:默认优先组合(招 2),确有 is-a 关系才用招 3——再次呼应【组合优于继承】的警语。
四、动手 Demo:类的三种使用方法
三招各演一遍:工具箱拿来就用、组合装引擎、继承造跑车。
class MathBox:
PI = 3.14
@staticmethod
def round2(x): return round(x, 2)
class Engine:
def start(self): return "引擎发动"
class Car:
def __init__(self): self.engine = Engine()
class SportsCar(Car):
def turbo(self): return "涡轮! " + self.engine.start()
print(MathBox.round2(3.14159))
print(Car().engine.start())
print(SportsCar().turbo())
实跑输出:
--------------------------------------------------------------------
类有三种使用方法
--------------------------------------------------------------------
拿到一个类, 有三招可用:
招式1 拿来就用: MathBox.round2(3.14159) = 3.14
招式2 装进去用: car.engine.start() -> 引擎发动
招式3 继承着用: sc.turbo() -> 涡轮加速! 引擎发动
招式 关系 关键词 例子
---------------------------------------------------------
拿来就用 调用方法 工具 Math/日期工具类
装进去用 有 (has-a) 组合 Car 装一台 Engine
继承着用 是 (is-a) 继承 SportsCar 是 Car
三招覆盖绝大多数设计: 无状态用招 1, 整体-部分用招 2,
真的【是一种】才用招 3——和 7.9 的警语【组合优于继承】接上了。
SportsCar 既用了招 3(继承 Car)又用了招 2(引擎装在车里)——三招可以叠着用。 判断用哪招就问一句:是工具(招 1)?有它(招 2)?是它(招 3)?
30 秒实验
- 给你的项目里的两个类判断关系:该用组合还是继承?说出理由。
- 把 7.3 的 Car 改成用继承实现,再对比两种写法的耦合程度。
常见误区
- 以为继承是【用类】的头等方式——多数场景组合更灵活,继承只留给真 is-a。
- 以为三种用法互斥——一个类常常同时被组合、被继承,招式可叠加。
自测三问(点开对答案)
1. 类的三种使用方法? —— 拿来就用(工具)、装进去用(组合 has-a)、继承着用(is-a)。 2. 7.3 拼装观对应哪一招? —— 招 2 组合——组件装进大件。 3. 默认优先哪一招?为什么? —— 组合——耦合更低、更易替换,呼应组合优于继承。- ☐ 下一节(7.12 在Java和.NET中有关OOP的知识不能少)
相关笔记
- 观点1:面向对象编程通过把组件拼装到一起构建程序 — 拼装观与组合用法一体两面
- LX_CH6_66 — 结构体打包数据,组合打包对象,思路一脉
- 💻 计算机是怎样跑起来的 · 索引