Files

52 lines
2.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 对象协议:身份、复制与依赖
> 原书依据:第 7 章,印刷页 31–39,PDF 页 42–50。
`Object` 提供许多基础协议。阅读子类时,既要看它新增了什么,也要看它重写了什么。
## 身份与相等
`==` 判断是否为同一对象;`=` 表达由类定义的相等关系。两个内容相同的集合可以是两个不同对象。修改其中一个是否影响另一个,还取决于它们内部引用是否共享。
`class` 返回所属类。`isMemberOf:` 针对确切的类;`isKindOf:` 包含继承关系。检查 `nil` 通常使用 `isNil` 或 `notNil`。面向协议设计时,不必为了发送每条消息都先做具体类判断。
## 浅复制复制的是哪一层
```text
原容器 ──→ 可变子对象
副本 ──→ 同一个可变子对象
```
浅复制产生新的外层对象,内部引用仍可指向相同子对象。给副本的某个槽位重新赋值,与修改该槽位所指子对象,是两种不同操作:前者改变副本自己的引用,后者可能被原对象观察到。
原书还讨论 `deepCopy` 和可被子类重写的 `copy`。深复制不应简单等同于“任意对象图都可以安全递归复制”:循环、共享关系和外部资源需要实现策略。本文没有对这些情况做运行验证。
## 表示与动态发送
| 消息 | 主要意图 |
| --- | --- |
| `printString` | 得到便于人阅读的表示 |
| `storeString` | 得到用于重建对象的源文本表示 |
| `perform:` | 用符号指定要发送的消息 |
| `perform:with:` | 动态发送带一个参数的消息 |
可读表示不等于持久化格式。动态发送也不是解析任意源代码:`perform:` 选择一个消息,而编译器求值会解释完整表达式。
## 用依赖通知连接对象
原书的依赖协议包含 `addDependent:`、`removeDependent:`、`changed:` 和 `update:`。模型改变后通知依赖者,让视图自行读取需要显示的状态。
```text
视图注册到模型
↓
模型状态修改 → changed: 某方面
↓
依赖者收到 update: → 重新读取模型 → 更新显示
```
通知描述“需要更新”,并不天然携带完整的新状态。实现时要明确通知粒度、订阅解除和是否可能形成递归更新。原书的键盘互斥示例说明对象之间可以靠依赖关系协调状态;最后的 MVC 案例继续使用这套机制。
## 阅读检查点
对一个复制操作,画出复制前后的引用箭头;对一次通知,列出谁订阅、谁修改、谁通知、谁重绘。这两张简图往往比逐个记忆方法名更能暴露误解。