一个 class 语句买到 5 种能力(可实例化/可继承/可多态/可封装/可扩展);加第 4 个子类时调用方 0 行改动——它省的不是打字量,是以后加东西的改动量。
第十一章讲完开发流程,正文到此收尾。这一章是三节回望,先说这个概念本身有多能生。
一、实测:一个语句买到五件事
可实例化:Shape(u"图形") 造出一个对象。
可继承:issubclass(Rect, Shape) 为 True。
可多态:同一个 x.area(),在 Shape/Rect/Circle 上给出 0/20/28.27 三种结果。
可封装:.name 只读,想改内部的 _nm 得走类里的方法。
可扩展:再加一个 Tri,4 个对象照样各自算对。
五件事全部来自同一个 class 语句,没有一样是额外加的开关。
二、原动力到底指什么
字面意思:一颗种子长出五棵树。 别的技术常常是【一个功能解决一个问题】:一个循环解决重复、一个 if 解决分支。 类不一样:它同时给了【怎么造】【怎么复用】【怎么替换】【怎么藏】【怎么加】。 所以叫【原动力】而不是【一个语法】——后面的设计、建模、流程,全是从这颗种子长出来的。
三、关键数字:加东西时改几行
加第 4 个子类 Tri 时,调用方 0 行改动。
原因很朴素:调用方写的是 x.area(),不是 if 是矩形 elif 是圆。
这是多态真正值钱的地方——它把【以后会加什么】这件事从调用方挪走了。
所以面向对象省的不是打字量,是【以后加东西时的改动量】。
四、动手 Demo:面向对象这一强大概念是原动力
定义 Shape 与两个子类,逐项验证五件事。 再加一个子类,看调用方要不要改。
class Shape:
def area(self): return 0
class Rect(Shape):
def __init__(self, a, b): self.a, self.b = a, b
def area(self): return self.a * self.b
class Circle(Shape):
def __init__(self, r): self.r = r
def area(self): return round(3.14159 * self.r ** 2, 2)
poly = [Shape(), Rect(4, 5), Circle(3)]
print([x.area() for x in poly]) # [0, 20, 28.27]
print(issubclass(Rect, Shape)) # True
class Tri(Shape):
def __init__(self, a, h): self.a, self.h = a, h
def area(self): return self.a * self.h / 2
poly.append(Tri(6, 4)) # 调用方一行没改
print([x.area() for x in poly]) # [0, 20, 28.27, 12.0]
实跑输出:
--------------------------------------------------------------------
面向对象这一强大概念是原动力
--------------------------------------------------------------------
一个 class 语句到底买到了几件事?**拿同一份代码逐项验:**
买到什么 实测证据 要改调用方吗
------------------------------------------------------------------------
可实例化 s = Shape(图形) 造出 1 个对象 不用
可继承 issubclass(Rect, Shape) 为 True 不用
可多态 同一 .area() 在 3 个对象上得 0/20/28.27 不用
可封装 .name 只读、改 _nm 得走类内 不用
可扩展 加 Tri 后 4 个对象得 0/20/28.27/12.0 不用
一个 class 买到的能力 5 种
加第 4 个子类要改调用方 0 行
三种图形共用一份 area() 是(调用方只有 1 处)
**这 5 种能力全部来自同一个语句**——**这就是【原动力】的字面意思:一颗种子长出五棵树。**
**注意第 5 行:加 Tri 时调用方 0 行改动**,因为调用方写的是 `x.area()` 而不是 `if 是矩形`。
**所以面向对象省的不是打字量,是【以后加东西时的改动量】。**
实测:一个 class 买到 5 种能力,加第 4 个子类时调用方 0 行改动。
因为调用方只认 x.area() 这个约定,不认具体是哪个类。
这就是【原动力】:后面所有设计手法,都是从这颗种子长出来的。
30 秒实验
- 数一数你项目里最常改的那个函数:加一种新类型要动它几行?
- 把那个 if/elif 链换成多态,看看调用方能不能一行不改。
常见误区
- 把【类】当成【带函数的字典】。它真正给的是替换能力,不是收纳能力。
- 以为多态是【语法糖】。它换掉的是调用方里的分支,那是要花钱维护的地方。
自测三问(点开对答案)
1. 实测一个 class 买到几种能力? —— 5 种:可实例化、可继承、可多态、可封装、可扩展。 2. 加第 4 个子类时调用方要改几行? —— 0 行,因为调用方写的是 x.area() 而不是 if 判断类型。 3. 【原动力】指什么? —— 一个语句同时长出五种能力;后面的设计、建模、流程都从这颗种子长出来。- ☐ 12.2 时代追上了面向对象
相关笔记
- 面向对象是软件开发的综合技术 — 这颗种子的第一次亮相
- 三大要素之二:实现调用端公用化的多态 — 多态省下的分支
- 时代追上了面向对象 — 当年为什么没火起来
- 🧩 面向对象是怎样工作的 · 索引