跳转到内容

Kotlin代码约定

来自代码酷
Admin留言 | 贡献2025年5月2日 (五) 00:14的版本 (Page creation by admin bot)

(差异) ←上一版本 | 已核准修订 (差异) | 最后版本 (差异) | 下一版本→ (差异)

Kotlin代码约定[编辑 | 编辑源代码]

Kotlin代码约定(Coding Conventions)是一套由JetBrains官方推荐的编程风格指南,旨在帮助开发者编写一致、可读且易于维护的Kotlin代码。这些约定涵盖了命名规则、代码布局、注释风格等多个方面,适用于个人项目和团队协作开发。

基本约定[编辑 | 编辑源代码]

命名规则[编辑 | 编辑源代码]

Kotlin遵循以下命名惯例:

  • 包名:全小写,不使用下划线(如org.example.project
  • 类/对象名:帕斯卡命名法(如MyClass
  • 函数/变量名:驼峰命名法(如calculateTotal
  • 常量名:全大写,下划线分隔(如MAX_COUNT
// 正确的命名示例
const val MAX_USERS = 100
class UserRepository {
    fun getUserById(id: Int): User {
        val currentUser = fetchUser()
        // ...
    }
}

代码布局[编辑 | 编辑源代码]

  • 使用4个空格缩进(不要使用Tab)
  • 大括号放在表达式开始的同一行
  • 当函数/类参数过多时,每个参数单独一行
// 正确的代码布局
class Person(
    val firstName: String,
    val lastName: String,
    val age: Int
) {
    fun greet() {
        println("Hello, $firstName!")
    }
}

函数设计[编辑 | 编辑源代码]

单一职责原则[编辑 | 编辑源代码]

每个函数应该只完成一个明确的任务:

// 不良实践
fun processUserData(user: User) {
    validate(user)
    saveToDatabase(user)
    sendWelcomeEmail(user)
    updateCache(user)
}

// 良好实践
fun processUserData(user: User) {
    validateUser(user)
    persistUser(user)
    notifyUser(user)
}

表达式函数[编辑 | 编辑源代码]

对于简单函数,使用表达式形式:

// 常规写法
fun isAdult(age: Int): Boolean {
    return age >= 18
}

// 表达式函数(推荐)
fun isAdult(age: Int) = age >= 18

空安全处理[编辑 | 编辑源代码]

Kotlin的空安全特性要求显式处理可空类型:

fun printLength(text: String?) {
    // 安全调用
    println(text?.length ?: "Text is null")
    
    // 或使用let作用域函数
    text?.let { 
        println(it.length) 
    }
}

集合操作[编辑 | 编辑源代码]

遵循函数式风格处理集合:

val numbers = listOf(1, 2, 3, 4, 5)

// 传统方式
val evenSquares = mutableListOf<Int>()
for (n in numbers) {
    if (n % 2 == 0) {
        evenSquares.add(n * n)
    }
}

// Kotlin风格(推荐)
val evenSquares = numbers
    .filter { it % 2 == 0 }
    .map { it * it }

类设计原则[编辑 | 编辑源代码]

数据类[编辑 | 编辑源代码]

对于纯数据载体,使用data class

// 自动生成toString(), equals(), hashCode(), copy()等
data class User(
    val id: Int,
    val name: String,
    val email: String
)

密封类[编辑 | 编辑源代码]

处理受限类层次结构:

sealed class Result<out T> {
    data class Success<out T>(val data: T) : Result<T>()
    data class Error(val exception: Exception) : Result<Nothing>()
}

fun handleResult(result: Result<String>) {
    when(result) {
        is Result.Success -> println(result.data)
        is Result.Error -> println("Error: ${result.exception}")
    }
}

作用域函数[编辑 | 编辑源代码]

合理选择作用域函数(let, run, with, apply, also):

graph TD A[是否需要返回接收者对象?] -->|是| B[需要配置对象属性?] A -->|否| C[需要处理可空性?] B -->|是| D[使用apply] B -->|否| E[使用also] C -->|是| F[使用let] C -->|否| G[需要扩展作用域?] G -->|是| H[使用run] G -->|否| I[使用with]

示例对比:

// let: 处理可空对象
user?.let { 
    println(it.name) 
}

// apply: 对象配置
val dialog = AlertDialog(context).apply {
    setTitle("Warning")
    setMessage("Are you sure?")
}

// run: 执行操作并返回结果
val result = service.run {
    initialize()
    fetchData()
}

协程实践[编辑 | 编辑源代码]

异步代码应遵循结构化并发原则:

// 不良实践(全局作用域)
GlobalScope.launch {
    // 可能造成内存泄漏
}

// 良好实践
viewModelScope.launch {
    try {
        val data = repository.fetchData()
        updateUi(data)
    } catch (e: Exception) {
        showError(e)
    }
}

性能考量[编辑 | 编辑源代码]

内联函数[编辑 | 编辑源代码]

对高阶函数使用inline减少运行时开销:

inline fun <T> measureTime(block: () -> T): T {
    val start = System.currentTimeMillis()
    val result = block()
    println("Time: ${System.currentTimeMillis() - start}ms")
    return result
}

延迟初始化[编辑 | 编辑源代码]

对耗资源属性使用延迟初始化:

class HeavyClass {
    val heavyData by lazy {
        // 仅在首次访问时计算
        computeHeavyData()
    }
}

测试规范[编辑 | 编辑源代码]

测试类应遵循Given-When-Then模式:

class CalculatorTest {
    @Test
    fun `addition should return sum of two numbers`() {
        // Given
        val calculator = Calculator()
        val a = 2
        val b = 3
        
        // When
        val result = calculator.add(a, b)
        
        // Then
        assertEquals(5, result)
    }
}

实际案例[编辑 | 编辑源代码]

电商应用中的商品折扣计算:

data class Product(
    val id: String,
    val name: String,
    val basePrice: Double,
    val discount: Double = 0.0
) {
    val finalPrice: Double
        get() = basePrice * (1 - discount.coerceAtLeast(0.0))
}

fun applyDiscounts(products: List<Product>, user: User): List<Product> {
    return products.map { product ->
        when {
            user.isPremium -> product.copy(discount = 0.2)
            product.basePrice > 100 -> product.copy(discount = 0.1)
            else -> product
        }
    }
}

总结[编辑 | 编辑源代码]

遵循Kotlin代码约定可以带来以下好处:

  • 提高代码可读性和一致性
  • 减少团队协作中的认知摩擦
  • 利用语言特性编写更安全的代码
  • 优化性能并减少常见错误

开发时应定期参考[官方编码约定](https://kotlinlang.org/docs/coding-conventions.html)并根据项目需求进行适当调整。