Kotlin 编码风格¶
此文件使用 Kotlin 特定内容扩展 common/coding-style.md。
格式¶
- 使用 ktlint 或 Detekt 强制风格
- 官方 Kotlin 代码风格(
gradle.properties中kotlin.code.style=official)
不可变性¶
- 优先使用
val而不是var— 默认使用val,仅在需要修改时使用var - 值类型使用
data class;公共 API 中使用不可变集合(List、Map、Set) - 状态更新使用写时复制:
state.copy(field = newValue)
命名¶
遵循 Kotlin 惯例:
- camelCase — 函数和属性
- PascalCase — 类、接口、对象、类型别名
- SCREAMING_SNAKE_CASE — 常量(const val 或 @JvmStatic)
- 接口前缀按行为命名,而不是 I:使用 Clickable,而不是 IClickable
Null 安全性¶
- 不使用
!!— 优先使用?.、?:、requireNotNull()或checkNotNull() - 对于作用域内的 null 安全操作使用
?.let {} - 从可能合理地没有结果的函数返回可空类型
// BAD
val name = user!!.name
// GOOD
val name = user?.name ?: "Unknown"
val name = requireNotNull(user) { "User must be set before accessing name" }.name
密封类型¶
对封闭的状态层次结构建模时使用密封类/接口:
sealed interface UiState<out T> {
data object Loading : UiState<Nothing>
data class Success<T>(val data: T) : UiState<T>
data class Error(val message: String) : UiState<Nothing>
}
对密封类型始终使用穷举的 when — 不使用 else 分支。
扩展函数¶
对实用操作使用扩展函数,但要便于发现:
- 文件名与接收者类型相关(StringExt.kt、FlowExt.kt)
- 限定作用域 — 不要为 Any 或过于通用的类型添加扩展
作用域函数¶
使用合适的作用域函数:
- let — null 检查 + 转换:user?.let { greet(it) }
- run — 使用接收者计算结果:service.run { fetch(config) }
- apply — 配置对象:builder.apply { timeout = 30 }
- also — 副作用:result.also { log(it) }
- 避免作用域函数深度嵌套(最多 2 层)
错误处理¶
- 使用
Result<T>或自定义密封类型 - 对可抛出代码的包装使用
runCatching {} - 绝对不要捕获
CancellationException— 始终重新抛出 - 不要在控制流中使用
try-catch
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 ev/ECC