🧩 第四章 面向对象编程技术:去除冗余、进行整理
📄 一句话概括

【调用端公用化】就是调用方只写一份——加一种形状,调用端一个字不用改。

📝 本节和前面几节的关系

4.4~4.7 讲完类的三件事,这一节讲第二个要素:同一句调用,不同的实现。

一、五个字的意思

公用=调用端的代码只有一份;私用=各形状的实现各自一份。 def total(shapes): return sum(s.area() for s in shapes)——这一行不知道有几形状、什么形状。 它只要求一件事:你能 area()。这就是 2.3 说的【消息的发送方法变得通用】。

二、实测对比

多态版:total 一行,实测 52.27431(矩形 24 + 圆 28.27431)。 不用多态版:if isinstance(s, Rect): s.area_rect()、elif isinstance(s, Circle): s.area_circle()。 调用端要写几行:每个形状 2 行 vs 1 行。 调用端知道几种?全部 vs 0 种。

三、差在加形状的那一刻

不用多态:加 2 行分支,而且要回去改那个已经测过的函数。 多态:加 1 个类,调用端 0 改动。 这就是开闭原则的全部内容:对扩展开放(加类),对修改关闭(不动调用端)。 注意:不是多态让程序变短,是多态让【加东西】不再碰【老东西】。

四、注意这不是【变形】

多态不是对象变了形状,是同一个名字在不同对象上有不同的实现。 s.area() 里的 s 一直没变,变的是【谁在响应这一次调用】。 所以多态的本质是【把知识放在谁那儿】——每个形状自己知道自己怎么算。 点开 2.3 会看到同一件事在比喻层面的说法;这里是它在代码里的样子。

五、动手 Demo:三大要素之二——实现调用端公用化的多态

两个形状各自实现 area,调用端只写一句 s.area()。 对比不用多态时要写多少分支。

class Rect:
    def __init__(self, w, h): self.w, self.h = w, h
    def area(self): return self.w * self.h

class Circle:
    def __init__(self, r): self.r = r
    def area(self): return 3.14159 * self.r * self.r

def total(shapes):
    return sum(s.area() for s in shapes)

print(total([Rect(6, 4), Circle(3)]))

实跑输出:

--------------------------------------------------------------------
三大要素之二——实现调用端公用化的多态
--------------------------------------------------------------------

  【调用端公用化】这五个字,说的是**调用方的代码只写一份**。

      多态版:def total(shapes): return sum(s.area() for s in shapes)
      实测 total → 52.27431

      不用多态版(思路):
        if isinstance(s, Rect):    s.area_rect()
        elif isinstance(s, Circle): s.area_circle()

                     不用多态          多态
  -----------------------------------------------
  调用端要写几行     每个形状 2 行     1 行
  加一种形状         加 2 行分支       加 1 个类
  调用端知道几种     全部              0 种

  **【公用化】这个词很准:调用端是【公用】的,各形状的实现是【私用】的。**
  实测两个形状各算各的(24 与 28.27431),**`total` 一个字没改。**

实测:total 一行算出 52.27431(矩形 24 + 圆 28.27431),total 不知道有几个形状、什么形状。 不用多态就要写 if/elif 分支:加一种形状加 2 行,调用端还得回头改。

30 秒实验

  1. 找一个写着 if isinstance 的函数,把分支搬进各自的类,看调用端还剩几行。
  2. 数一数【加一种新东西】要在几个文件里改。

常见误区

  1. 以为多态是对象变形。是同一个名字在不同对象上有不同实现。
  2. 以为多态只是让代码变短。真正的价值是加东西不碰老代码。
自测三问(点开对答案) 1. 【调用端公用化】是什么意思? —— 调用方的代码只写一份,各形状的实现各自一份——调用端不知道有几种形状。 2. 多态版和 if 分支版差在哪? —— 调用端每形状 2 行 vs 1 行;加一种形状是加 2 行分支(还要改老代码)vs 加 1 个类(调用端不动)。 3. 多态的本质是什么? —— 同一句调用,不同对象有不同实现——把知识放在各自的对象那儿,而不是放在调用方。

相关笔记