SuperAPI AI 工具集

encapsulation

编程与开发

查看项目

更新于 10-16 04:39

技能介绍

用途

封装是一项面向对象设计技能,用于在类设计中隐藏内部状态、只暴露行为而非数据,并通过方法控制对状态的访问。资料指出,公开字段会让任何人修改对象内部、绕过校验并破坏不变量,而封装用于保护数据完整性。

何时使用

资料列出以下适用场景:

  • 设计带状态的类
  • 想图方便把字段设为 public
  • 外部代码直接修改对象状态
  • 直接访问可能破坏不变量

核心原则

资料提出“铁律”:绝不直接暴露内部状态,始终用方法控制访问。没有例外,不因“更简单”“我们信任调用方”“这只是数据”“getter/setter 太啰嗦”而破例。

检测:暴露状态坏味道

如果内部状态可直接访问,就应停止。资料给出的违规示例中,BankAccount 的 balance 和 transactions 为 public,调用方可以把余额设为负数、清空审计记录。问题包括:变更无校验、不变量容易被破坏、没有审计轨迹、无法更改内部表示。

正确模式:私有状态,公开方法

资料演示将 _balance、_transactions 设为 private,通过 get balance() 只读访问,通过 deposit()、withdraw() 做正数校验与余额校验并记录交易,getTransactionHistory() 返回副本。这样不变量受到保护,非法赋值会报错。

封装技巧

  1. 私有字段:如 User 的 _password 私有,通过 setPassword() 校验长度并哈希,通过 checkPassword() 验证。
  2. 用 readonly 提供只读访问:如 Config 的 apiUrl、timeout 为 readonly,在构造函数中赋值。
  3. 返回副本而非引用:Order 的 getItems() 应返回 [...this._items] 或 ReadonlyArray<OrderItem>,而不是直接返回 this._items。
  4. 在 setter 中校验:如 Product 的 price setter 校验不能为负、不能过高。

压力抵抗协议

资料针对四种常见压力给出回应:

  • “更简单”:现在代码少,以后 bug 多;封装防止非法状态。做法是私有字段加方法,多出的代码就是校验。
  • “我们信任调用方”:团队会扩大、代码会演进、错误会发生;应在代码中强制保护不变量,而非依赖调用方自律。
  • “这只是数据”:数据也有规则,邮箱有格式、年龄有范围;纯数据用 DTO/接口,类等于行为加封装。
  • “getter/setter 啰嗦”:TypeScript 有简洁的 get/set 语法,get balance() 并不啰嗦。

红旗清单

资料列出应停止并重新考虑的信号:可变字段带 public 关键字、外部直接属性赋值、按引用返回数组/对象、状态变更无校验、不变量只写在文档而未强制。出现这些就意味着应封装状态。

快速参考

暴露(坏)对封装(好):public balance 对 private _balance 加 deposit()/withdraw();return this.items 对 return [...this.items];直接修改对带校验的方法;信任调用方对在类中强制。

常见合理化借口(均无效)

资料逐条反驳:“更简单”是写起来简单、维护更难;“我们信任调用方”是代码应强制而非信任;“只是数据”是数据有约束应强制;“啰嗦”是 TypeScript getter 很简洁;“过度工程”其实只是工程。

底线

私有状态、公开方法、每次变更都校验。绝不直接暴露内部状态,返回集合副本,在 setter 中校验。封装保护不变量并支持安全演进。

限制

资料未提供该技能的具体安装命令、运行环境要求、收费方式或平台支持信息,暂未提供。