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

以对象为中心,说的是把数据和操作它的代码放在一起,让别人别乱碰;class 那三个字母只是外壳。

📝 本节和前面几节的关系

1.1 说了第一层是编程技术,这一节讲它最核心的一条主张——为什么非得把数据和方法绑在一起。

一、数据与操作,本来是分家的

过程式的写一个购物车是这样的:一个字典存 items 和 total,一个函数 add_item(cart, name, price) 负责改它。 数据在一边,操作在另一边,靠函数参数把它们拉到一起。 小规模时这没问题。问题在【谁都能改】:任何一段代码拿到 cart,都能往里面塞一个不存在的键。

二、绑在一起之后多了什么

换成类以后,items 和 total 变成 self. 上的字段,add 变成方法——数据和改它的代码关进了同一个盒子。 盒子外面只剩几个口:想改数据,只能走方法。 关键收益不是省了几行代码,是【规则有了落脚点】。比如【加商品必须同时更新总价】这条规则,现在只可能写在 add 里。

三、封装不是保密,是划边界

很多人把封装理解成【藏起来不让人看】,偏了。 封装的实质是划一条边界,并规定只能从哪儿过。 藏起来只是手段,目的是让【不合法】这件事在语法上就做不到,而不是靠文档和自觉。 private 也好、Python 的下划线约定也好,都是这条边界的记号。

四、这一步是后面所有技术的地基

封装立住了,多态才有意义——如果任何代码都能绕过方法直接改数据,运行时挑哪个实现就无所谓了。 继承才有意义——子类覆写方法,前提是【调用必须走方法】。 所以第 4 章讲三大要素时,会先讲类的三种功能(汇总、隐藏、创建很多个),再讲多态和继承。顺序不是随便排的。

五、动手 Demo:以对象为中心编写软件的开发方法

同一个购物车,字典版和类版各写一遍,比一比【错了能不能被发现】。 两段代码里 total 出现的次数几乎一样——差别不在字数上。

# 字典版:数据与操作分家
cart = {"items": [], "total": 0}
def add_item(cart, name, price):
    cart["items"].append(name)
    cart["total"] += price

# 类版:数据与操作绑在一起
class Cart:
    def __init__(self):
        self.items = []
        self.total = 0
    def add(self, name, price):
        self.items.append(name)
        self.total += price

c1 = {"items": [], "total": 0}
c2 = Cart()
add_item(c1, "键盘", 199)
c2.add("键盘", 199)
print("字典版", c1["total"], "类版", c2.total)

实跑输出:

--------------------------------------------------------------------
以对象为中心编写软件的开发方法
--------------------------------------------------------------------

  同一个购物车,两种写法。先看数据与操作分开的:

      cart = {"items": [], "total": 0}
      def add_item(cart, name, price):
          cart["items"].append(name)
          cart["total"] += price
      add_item(cart, "键盘", 199)
      add_item(cart, "鼠标", 89)

  再看数据与操作绑在一起的:

      class Cart:
          def __init__(self):
              self.items = []
              self.total = 0
          def add(self, name, price):
              self.items.append(name)
              self.total += price
      cart = Cart()
      cart.add("键盘", 199)
      cart.add("鼠标", 89)

  实测统计——`total` 在字典版出现 2 次、类版 2 次,**次数几乎一样**。
  差别不在这里:

    字典版:键是字符串,写错了不会报错,只会悄悄多出一个键
    类版:  字段名写错,多数语言能当场查出来

  **这不是风格问题,是【错了能不能被发现】的问题:**

                         字典版               类版
  -----------------------------------------------------------
  键名写错时             运行时才炸           多数能静态查出
  谁知道 cart 有什么     看文档/猜           看类定义
  加一个字段             记得同步所有函数     写在类里就一处

  **以对象为中心,说的是【把数据和操作它的代码放在一起,让别人别乱碰】。**
  这一步做到了,才有后面那些东西——封装、多态、继承,都建在这上面。

两版跑出来的总价一样(199),差别在【键名写错时谁替你抓】。 字典版的 "totol" 不会报错,只会悄悄多一个键;类版编译期或运行早期就能查出。

30 秒实验

  1. 把 cart["total"] 故意写成 cart["totol"],看程序是报错还是默默算错。
  2. 数一数你的项目里,有多少地方可以绕过方法直接改对象字段。

常见误区

  1. 以为封装=加 private。加关键字只是记号,真东西是【只留几个口】。
  2. 以为类只是【函数加个壳】。它真正提供的是【规则的落脚点】。
自测三问(点开对答案) 1. 以对象为中心的核心主张是什么? —— 把数据和操作它的代码放在一起,只留几个规定的入口,别人不能绕过。 2. 字典版和类版最大的差别在哪? —— 不在代码长短,在【键名或字段名写错时,能不能被当场发现】。 3. 为什么说封装是后面所有技术的地基? —— 因为多态和继承都建立在【调用必须走方法】这个前提上;能绕过方法直接改数据,它们就失去意义。

相关笔记