以对象为中心,说的是把数据和操作它的代码放在一起,让别人别乱碰;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 秒实验
- 把
cart["total"]故意写成cart["totol"],看程序是报错还是默默算错。 - 数一数你的项目里,有多少地方可以绕过方法直接改对象字段。
常见误区
- 以为封装=加
private。加关键字只是记号,真东西是【只留几个口】。 - 以为类只是【函数加个壳】。它真正提供的是【规则的落脚点】。
自测三问(点开对答案)
1. 以对象为中心的核心主张是什么? —— 把数据和操作它的代码放在一起,只留几个规定的入口,别人不能绕过。 2. 字典版和类版最大的差别在哪? —— 不在代码长短,在【键名或字段名写错时,能不能被当场发现】。 3. 为什么说封装是后面所有技术的地基? —— 因为多态和继承都建立在【调用必须走方法】这个前提上;能绕过方法直接改数据,它们就失去意义。- ☐ 下一节(1.3 从编程语言演化为综合技术)
相关笔记
- 面向对象是软件开发的综合技术 — 这一步在全景图里的位置
- 原因之一:OOP结构复杂 — 类为什么让人眼花
- ☕ Java基础 · 索引 — 类的语法细节在那里
- 🧩 面向对象是怎样工作的 · 索引