📄 一句话概括
类干的其实是三件事:汇总、隐藏、创建很多个——而且这个顺序不能反。
📝 本节和前面几节的关系
4.1 说类治第一种重复,这一节把它拆开:这个【类】到底做了什么。
一、三件事
汇总——把该在一起的数据和操作它的代码放进同一个盒子。 隐藏——盒子上只开几个口,别的都碰不到。 创建很多个——同一个盒子能复制出无数个各自独立的实例。 这三件事合起来,才是完整的【类】。缺一件就不成立。
二、顺序不能反
先汇总,才谈得上隐藏——东西没装进来,藏什么呢。 先隐藏,才谈得上【每个都有自己的状态】——口子不固定,状态就守不住。 所以看书时这个顺序是有讲究的:4.4 汇总、4.5 隐藏、4.6 创建很多个。 这不是排版顺序,是依赖顺序。
三、一个最小的类就能演一遍
Counter 里:made 记账、_n 装数、add() 加一、value() 取值。
实测:a = Counter()、b = Counter(10)、a.add() 之后,a.value() 是 1,b.value() 是 10。
两个实例互不影响——这是【创建很多个】的证明。
Counter.made 是 2——这是【类变量全体共享】的证明。
四、为什么叫功能不叫特征
因为这三件事都是它能替人做的事,不是它长什么样。 判断一个类写得好不好,就看这三件事它做了几件: 数据和方法是不是在一起?外面绕不绕得过去?能不能造很多个? 三个都答【是】,才算一个合格的类。
五、动手 Demo:三大要素之一——具有三种功能的类
写一个最小的 Counter,让三件事同时在场。 造两个实例,看它们是不是互不影响。
class Counter:
made = 0
def __init__(self, start=0):
self._n = start
Counter.made += 1
def add(self):
self._n += 1
return self._n
def value(self):
return self._n
a = Counter(); b = Counter(10); a.add()
print(a.value(), b.value(), Counter.made)
实跑输出:
--------------------------------------------------------------------
三大要素之一——具有三种功能的类
--------------------------------------------------------------------
类这一个东西,其实干了三件事:**汇总、隐藏、创建很多个。**
一个最小的类就能把三件都演一遍:
class Counter: made/_n/add()/value()
a = Counter(); b = Counter(10); a.add()
功能 在这个类里是什么 实测
----------------------------------------------------------
汇总 数据 _n 和方法 add 待在一起 1 处
隐藏 _n 只能通过 add/value 碰 绕不过去
创建很多个 每 new 一个就有自己的一份 _n 已造 2 个
**顺序不能反:先汇总,才谈得上隐藏;先隐藏,才谈得上【每个都有自己的状态】。**
实测两个实例互不影响:`a.value()` = 1,`b.value()` = 10。
**这三条就是 4.4、4.5、4.6 三节的正题。**
实测:a.value() 是 1,b.value() 是 10,Counter.made 是 2。
两个实例互不影响,说明【创建很多个】成立;made 只有一个,说明类变量全体共享。
30 秒实验
- 拿你自己写的一个类,逐条对:汇总了吗、隐藏了吗、能造很多个吗。
- 找一个只有静态方法的类,看它缺了哪一条。
常见误区
- 以为类就是一个【结构体加函数】。那是汇总,缺了隐藏和创建很多个。
- 以为三件事可以随便挑着做。顺序和依赖是有讲究的。
自测三问(点开对答案)
1. 类干了哪三件事? —— 汇总(数据和方法在一起)、隐藏(只留几个口)、创建很多个(每个实例有自己的状态)。 2. 为什么说顺序不能反? —— 先汇总才谈得上隐藏;先隐藏才谈得上每个实例都有自己的状态——这是依赖顺序,不是排版顺序。 3. 怎么判断一个类写得好不好? —— 看三件事做了几件:数据和方法在一起吗、外面绕得过去吗、能造很多个吗。- ☐ 下一节(4.4 类的功能之一:汇总)
相关笔记
- 类的功能之一:汇总 — 第一件事
- 对三大要素的总结 — 三件事的合流
- 以对象为中心编写软件的开发方法 — 盒子最初的样子
- 🧩 面向对象是怎样工作的 · 索引