enum、protocol、extension 与泛型
这些能力让状态更清楚、依赖更可替换,而不需要复杂继承树。
用你的前端经验理解
protocol 与 TS interface 有相似用途,但包含更严格的遵循规则;带关联值 enum 很适合替代多个互相矛盾的布尔变量。
为什么需要它
enum 适合表达有限且互斥的业务状态,protocol 描述一种能力,泛型让算法在保留类型信息的同时复用。它们解决不同问题。例如加载页面不应该同时 isLoading=true、hasError=true、hasData=true;用一个带关联值的 enum,可以让不合理的组合更难被构造出来。
它是怎样工作的
协议描述调用者需要什么,不要求对象属于某个继承树。真实网络仓库与测试仓库都可以满足同一协议。extension 可以补充方法或协议遵循,但不能凭空给已有类型添加普通存储属性。泛型中的约束决定能对参数做哪些操作;看到 some 与 any 时应意识到前者隐藏但保留具体类型,后者表达可容纳符合协议的值。
把关键概念连起来
enum
用 loading、success(data)、failure(error) 表达互斥状态;switch 让遗漏的状态更容易暴露。
protocol + extension
定义行为约定,并扩展类型的能力。可用于注入网络服务的真实实现与测试替身。
泛型
保留具体类型关系、复用算法。some Protocol 隐藏某个确定类型,any Protocol 表示可容纳遵循协议的值,两者不等价。
enum LoadState { case idle case loading case loaded([String]) case failed(String)}用于理解当前概念的代码片段;部分示例需要放入对应工程与作用域,并补齐上下文。
把页面状态改为明确的分支
- 定义 idle、loading、loaded([String]) 和 failed(String)。数据和错误只存在于需要它们的状态里。
- 界面通过 switch 决定显示按钮、进度、列表或重试。编译器要求覆盖所有枚举情况,有助于避免新增状态遗漏页面。
- 再为加载服务定义协议,让预览注入立即成功、空结果和失败实现,而无需真正发请求。
这里需要你亲自判断
不要为了“架构高级”给每个 struct 都配一个 protocol;只有确实存在替换需求时才抽象。
做一个小练习
把 isLoading、hasError、hasData 三个 Bool 改成一个加载状态 enum。
- 用 enum 表达未登录、登录中、已登录用户和登录失败。
- 说明“已登录但没有用户对象”如何通过关联值模型被避免。
展开参考思路与验收标准
已登录状态应携带所需用户数据,而不是额外维护一个可能为 nil 的全局 user。协议只暴露页面需要的加载能力,不应为了可测试性复制真实服务的全部内部方法。