🧩 第一章 面向对象:让软件开发变轻松的技术
📄 一句话概括

难不是错觉:两段代码行数只差 7 行,概念差 7 个。本书把难处归成三条——结构复杂、滥用比喻、概念抽象。

📝 本节和前面几节的关系

1.1~1.3 讲清了它是什么、怎么来的,这一节开始处理【为什么学不会】。

一、先把难度量化

同一件事写成两段代码:过程式 9 行、对象式 16 行——行数只差 7 行。 但对象式那边要先懂的概念是 10 个:函数、循环、类、继承、构造、属性访问、父类调用、抽象方法、异常、元组解包。 过程式只要 3 个:函数、分支、循环。 多 7 行,多 7 个概念。难度差在这里,不在代码长度。

二、三条原因总览

本书把难处归成三条,每条各占一节: 结构复杂(1.5)——语言里的构造比结构化语言多一大截。 滥用比喻(1.6)——拿现实世界打比方,打到一半对不上。 概念抽象(1.7)——同一个词在不同层指不同东西。 这三条是递进的:先是看得见的语法多,再是解释方式歪,最后是词本身有歧义。

三、为什么作者的解法是讲 What 和 Why

三条难处里,前两条靠讲清楚就能治:构造多,就一个一个讲它为什么存在;比喻歪,就把边界划出来。 第三条最难,只能靠反复交代【现在站在哪一层】。 所以全书的写法是:What 讲透、Why 讲透、How 给最小限度(1.8 展开)。

四、这三条分别在哪三节展开

1.5 讲第一条,落点在一个最小的完整类。 1.6 讲第二条,落点在哪些比喻对不上。 1.7 讲第三条,落点在同一个词的三层含义。 记住这个顺序,后面读第 4 章时会轻松很多——那一章的三大要素正是【结构复杂】的正题。

五、动手 Demo:面向对象难的原因

把两段【算面积】的代码摊开,按代码里实际出现的写法逐条判断涉及哪些概念。 不看行数,看概念数。

proc = (
    "def area(kind, a, b):\n"
    "    if kind == 1:\n"
    "        return a * b\n"
    "    return 3.14 * a * a\n"
    "def total(xs):\n"
    "    s = 0\n"
    "    for x in xs:\n"
    "        s += area(x[0], x[1], x[2])\n"
    "    return s\n"
)
oop = (
    "class Shape:\n"
    "    def __init__(self, name):\n"
    "        self.name = name\n"
    "    def area(self):\n"
    "        raise NotImplementedError\n"
    "class Rect(Shape):\n"
    "    def __init__(self, w, h):\n"
    "        super().__init__('矩形')\n"
    "        self.w, self.h = w, h\n"
    "    def area(self):\n"
    "        return self.w * self.h\n"
)
MARKS = [("函数", "def "), ("分支", "if "), ("循环", "for "),
         ("类", "class "), ("继承", "class Rect"),
         ("构造", "__init__"), ("属性访问", "self."),
         ("父类调用", "super()"),
         ("抽象方法", "NotImplementedError"),
         ("异常", "raise "), ("元组解包", "self.w, self.h")]
for name, src in (("过程式", proc), ("对象式", oop)):
    hit = [n for n, m in MARKS if m in src]
    print(name, "行数", len(src.rstrip().split(chr(10))), "概念", len(hit))

实跑输出:

--------------------------------------------------------------------
面向对象难的原因
--------------------------------------------------------------------

  难,不是错觉。把两段代码摊开逐条数,就看得见。

  实测统计——按代码里实际出现的写法逐条判断:

  指标             过程式     对象式
  -----------------------------------
  代码行数         9 行       16 行
  要先懂的概念     3 个       10 个

  过程式涉及:函数、分支、循环
  对象式涉及:
      函数、循环、类、继承
      构造、属性访问、父类调用、抽象方法
      异常、元组解包

  **多出 7 行,多出 7 个概念——难就难在这儿。**
  而且这些概念不是【新语法糖】:`class` 三个字母谁都认得,
  **难的是它隐含的那套规则——谁能改、谁管谁、什么时候用哪个。**

  所以本书把难处归成三条,后面三节各讲一条:

  原因         一句话                               在哪节
  ---------------------------------------------------------
  结构复杂     语言里的构造比结构化语言多一大截     1.5
  滥用比喻     拿现实世界打比方,打到一半对不上     1.6
  概念抽象     同一个词在不同层指不同东西           1.7

实测:过程式 9 行/3 个概念,对象式 16 行/10 个概念。 多 7 行,多 7 个概念——难点不在长度,在要同时装进脑子里的东西变多了。

30 秒实验

  1. 数一数你最近写的一个类,用到了这 11 个概念里的几个。
  2. 找一句你解释不清的 OOP 术语,看它是不是属于【比喻歪了】那一类。

常见误区

  1. 以为难是因为自己笨。是概念密度确实高。
  2. 以为把语法背完就不难了。结构只是第一条,还有比喻和歧义两条。
自测三问(点开对答案) 1. 面向对象难的三条原因是什么? —— 结构复杂(构造多)、滥用比喻(比方对不上)、概念抽象(一个词多层含义)。 2. 两段代码对比说明了什么? —— 行数只差 7 行,但要先懂的概念多 7 个——难度来自概念密度,不来自代码长度。 3. 这三条为什么是递进的? —— 先是看得见的语法多,再是解释方式歪,最后是词本身有歧义,一层比一层隐蔽。

相关笔记