一、核心原则
当你的设计依赖“引用语义 + 动态派发 + 继承层次”时,用 OOP 更自然。
当你设计依赖“行为契约 + 值类型 +组合能力”时,用 POP 更好。
二、典型推荐 OOP 的场景
| 场景 | 原因 | 示例 |
|---|---|---|
| 1️⃣ UIKit / AppKit 或其他框架依赖类层级 | 框架 API 已经用 class、多态依赖 vtable | UIView 子类化 |
| 2️⃣ 状态共享 / 引用语义很重要 | class 是引用类型,值类型无法共享状态 | 一个共享缓存、或单例对象 |
| 3️⃣ 复杂动态派发 | 动态选择具体实现时频繁切换类型 | 游戏对象系统:不同 Enemy 类型动态选择方法 |
| 4️⃣ 多态行为依赖继承链 | 子类依赖父类部分实现 | NSOperation 子类重写 main() 方法 |
| 5️⃣ 生命周期管理依赖 ARC 引用 | struct 无法被弱引用 | 复杂对象图中,循环引用管理需要 class |
三、示例对比
1️⃣ 引用语义场景
class Counter {
var value = 0
func increment() { value += 1 }
}
let c1 = Counter()
let c2 = c1
c2.increment()
print(c1.value) // 输出 1 ✅ 共享引用
- struct / POP 无法共享同一状态(值类型复制)
- 这里用 class 更自然
2️⃣ UIKit 子类化
class CustomButton: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
// 调整布局
}
}
- 必须继承 UIButton
- protocol + struct 无法替代
3️⃣ 复杂多态逻辑依赖继承
class Animal {
func speak() { print("Animal") }
}
class Dog: Animal {
override func speak() { print("Woof") }
}
class Cat: Animal {
override func speak() { print("Meow") }
}
let a: Animal = Dog()
a.speak() // Woof
- 动态类型切换 → class 多态天然
- 用 POP struct + protocol 会复杂,需要类型擦除或泛型包装
四、工程级总结规则
- 依赖引用语义 → OOP
- 依赖现有 class 框架 → OOP
- 多态深层继承链、动态行为复杂 → OOP
- 可复用、解耦、值类型组合 → POP
- 共享状态小、性能敏感 → POP + struct +泛型
🔑 口诀
POP 做能力组合、值类型、解耦复用;
OOP 做状态共享、引用语义、深层多态。