mcpField
K
kotlin-control-flow

kotlin-control-flow

github.com/chrisbanes开发1.1k1.2k 次安装1 天前更新
代码仓库

关于 kotlin-control-flow

面向开发者和编码 Agent 的 Kotlin 控制流技能,指导选择 subject `when`、守卫分支和穷尽匹配,并强调使用项目构建工具验证。

主要功能

  1. 01选择 `when` 或 `if` 的指导
  2. 02用守卫分支细化条件
  3. 03封闭类型的穷尽匹配
  4. 04用提前返回处理无效状态
  5. 05基于智能转换处理分支数据
  6. 06使用项目构建工具验证

适用场景

  1. 01重构针对同一值的重复条件
  2. 02处理枚举或密封类型结果
  3. 03避免无效或可空状态进入主逻辑

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/chrisbanes/skills --skill kotlin-control-flow

安装后在 Claude Code 中输入/kotlin-control-flow确认已加载。

详细介绍

Kotlin 控制流

核心原则

明确指出被分类的值,将分支局部谓词保留在其所属分支中,并让编译器证明封闭域的覆盖完整性。

步骤

  1. 为被分类的值命名。如果每个分支都对它进行测试,请使用 when (subject);否则保留无主题的 when 或 if 链。

  2. 选择分支形式:

    代码形式优先选择
    单个被分类的值when (subject)
    互不相关的布尔条件无主题的 when 或 if/else
    主要情况加上分支局部谓词守卫条件
    主流程之前的无效输入提前返回、require 或 check
    封闭的值返回域穷尽式 when 表达式
    开放输入或有意设置的兜底分支显式 else
  3. 仅在主题 when 中、主要条件之后使用守卫,且额外谓词属于该分支,并且仍有不带守卫的分支处理主要条件时才使用。将带守卫的分支放在前面。将逗号分隔的条件拆开,而不是只对其中一个添加守卫。Kotlin 2.2 起支持守卫。遵循显式的 languageVersion 设置;否则,项目构建文件或版本目录中的 Kotlin 版本足以确认支持,因此不要因为缺少进一步证明而拒绝使用守卫。

  4. 对于封闭的枚举、布尔值、密封类型或可空封闭类型,列出所有情况并省略 else。按值匹配对象,使用 is 匹配类和数据类子类型。如果输入是开放的服务器/平台值,或确实需要兜底/日志记录,则保留 else。为每个携带数据的子类型分别添加自己的 is 分支,包括被兜底分支合并处理的子类型。当其数据会影响映射或安全处理时,检查结果或改动必须展示智能类型转换后的成员访问,即使公开值保持不变:

    is Outcome.Failed -> safeFailureLabel(outcome.reason)
    

    is 检查会对 outcome 执行智能类型转换,因此分支无需强制转换即可使用 reason;辅助函数名称仅用于说明。仅列出情况,或让调用者自行检查原始值,都不算完整的分支指导。如果数据不影响结果,就在该 is 分支中保留当前值;不要凭空添加对数据的使用。

  5. 仅当提前返回能从主流程中移除无效或可空状态时才使用。对于表达清理、事务或错误处理的嵌套结构,应予以保留。

  6. 验证智能类型转换仍然有效,无需使用 as、!!、可变临时变量或重复强制转换。如果无效,则保留原有形式或进行更小幅度的重构。

  7. 使用项目自身的构建工具编译并测试;如果是 Gradle 项目,请使用 Gradle run 工作流,切勿直接运行 Gradle。失败时,回到最小适用的前置步骤,或保留先前的形式。完成标准是:读者能清楚看出主题、兜底分支和相关分支数据,并且最终结构更易浏览。

示例

使用带守卫的分支细化单种情况,而不是嵌套 if:

return when (event) {
    is Event.Message if event.isUnread -> Row.Highlighted(event.message)
    is Event.Message -> Row.Normal(event.message)
    Event.Empty -> Row.Empty
}

当重复条件用于分类同一个值时,使用主题 when;如果 null 是较大分类中的一种情况,则将其作为一个分支:

return when (val selected = selection) {
    null -> SelectionUi.None
    is Selection.Single if selected.item.isArchived -> SelectionUi.Archived(selected.item)
    is Selection.Single -> SelectionUi.Active(selected.item)
    is Selection.Multiple -> SelectionUi.Count(selected.items.size)
}

不要在不支持的 Kotlin 版本中引入守卫,不要将互不相关的布尔检查强行放入主题 when,不要移除开放世界的兜底分支,也不要扁平化会模糊清理、事务或错误处理的代码。

相关内容

评论

支持 Markdown