Kotlin模式

Mattakushi4322026-10-25查看 1899复制 616

何时激活:Kotlin 习惯用法、数据类、密封类、when 表达式、伴生对象、运算符重载、扩展函数、DSL、作用域函数

Download (.md)

📘如何使用这个技能

  1. 1
    复制技能内容·点击上方「Copy SKILL.md」复制全部内容,或 Download 下载到本地
  2. 2
    打开你的 AI 客户端·支持 Claude Code、Trae、Cursor、ChatGPT、DeepSeek、Kimi 等任意 AI 助手
  3. 3
    粘贴为系统提示/知识文件·Claude Code:放入 .claude/skills/ 目录;普通对话:作为首条消息发送并说「请严格按这份技能文档执行」
  4. 4
    直接提出你的需求·AI 会按技能定义的工作流、格式和约束来处理,无需再解释背景

💡 提示:技能生效后,每次对话只需一句需求,AI 会按 SKILL.md 的流程执行。

SKILL.md5498 chars
---
name: kotlin-patterns
description: "When to activate: Kotlin idioms, data classes, sealed classes, when expression, companion objects, operator overloading, extension functions, DSL, scope functions"
origin: zakr
metadata:
  namespace: zakr/devtools-pack
  version: 1.0.0
  category: engineering
  language: java-kotlin
  platforms: [claude-code, codex, gemini-cli, cursor, aider, windsurf]
---
# Kotlin Patterns & Idioms

## Data Classes & Destructuring

```kotlin
data class User(
    val id: Long,
    val name: String,
    val email: String,
    val role: Role = Role.USER
)

// Destructuring
val (id, name, email) = user

// Copy with changes (immutable update)
val updated = user.copy(name = "Jane", role = Role.ADMIN)
```

## Sealed Classes & When

```kotlin
sealed class Result<out T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Error(val message: String, val cause: Throwable? = null) : Result<Nothing>()
    data object Loading : Result<Nothing>()
}

fun <T> Result<T>.getOrElse(default: T): T = when (this) {
    is Result.Success -> data
    is Result.Error -> default
    Result.Loading -> default
}

// Exhaustive when (no else needed for sealed)
fun handleResult(result: Result<User>) = when (result) {
    is Result.Success -> println("Got user: ${result.data.name}")
    is Result.Error -> println("Error: ${result.message}")
    Result.Loading -> println("Loading...")
}
```

## Extension Functions

```kotlin
fun String.isValidEmail(): Boolean =
    matches(Regex("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$"))

fun <T> List<T>.secondOrNull(): T? = if (size >= 2) get(1) else null

fun BigDecimal.format(currency: Currency = Currency.getInstance("USD")): String =
    NumberFormat.getCurrencyInstance().apply { this.currency = currency }.format(this)

// Extension on existing types
fun LocalDate.isWeekend(): Boolean = dayOfWeek in setOf(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY)
```

## Scope Functions

```kotlin
// let — transform nullable or create a scope
user?.let { println("User: ${it.name}") }
val length = name?.let { it.trim().length } ?: 0

// apply — configure object, returns receiver
val user = User().apply {
    name = "Alice"
    email = "alice@example.com"
}

// run — execute block, return result
val summary = user.run {
    "${name} (${email})"
}

// also — side effects, returns receiver
repository.save(user).also { log.info("Saved user ${it.id}") }

// with — call multiple methods, no receiver
val result = with(stringBuilder) {
    append("Hello")
    append(", World")
    toString()
}
```

## Companion Objects & Factory Methods

```kotlin
class ApiClient private constructor(
    private val baseUrl: String,
    private val apiKey: String
) {
    companion object {
        fun create(baseUrl: String, apiKey: String): ApiClient {
            require(baseUrl.isNotBlank()) { "baseUrl cannot be blank" }
            require(apiKey.length >= 32) { "apiKey must be at least 32 chars" }
            return ApiClient(baseUrl, apiKey)
        }

        val DEFAULT = create("https://api.example.com", System.getenv("API_KEY") ?: "")
    }
}
```

## Operator Overloading

```kotlin
data class Money(val amount: BigDecimal, val currency: String) {
    operator fun plus(other: Money): Money {
        require(currency == other.currency) { "Currency mismatch" }
        return copy(amount = amount + other.amount)
    }

    operator fun times(factor: Int): Money = copy(amount = amount * factor.toBigDecimal())
    operator fun compareTo(other: Money): Int = amount.compareTo(other.amount)
}

val total = Money(10.bd, "USD") + Money(5.bd, "USD") // Money(15, USD)
```

## Type-Safe DSL Builder

```kotlin
@DslMarker annotation class EmailDsl

@EmailDsl
class EmailBuilder {
    var to: String = ""
    var subject: String = ""
    private val body = StringBuilder()

    fun body(block: StringBuilder.() -> Unit) { body.block() }
    fun build() = Email(to, subject, body.toString())
}

fun email(block: EmailBuilder.() -> Unit): Email = EmailBuilder().apply(block).build()

// Usage
val msg = email {
    to = "user@example.com"
    subject = "Welcome"
    body { append("Hello, World!") }
}
```

## Delegation

```kotlin
// Property delegation
class UserPreferences(private val prefs: SharedPreferences) {
    var darkMode: Boolean by prefs.boolean("dark_mode", default = false)
    var language: String by prefs.string("language", default = "en")
}

// Interface delegation
class LoggingRepository(
    private val delegate: UserRepository
) : UserRepository by delegate {
    override fun save(user: User): User {
        log.info("Saving user ${user.id}")
        return delegate.save(user).also { log.info("Saved user ${it.id}") }
    }
}
```

## Inline Functions & Reified Types

```kotlin
inline fun <reified T> String.fromJson(): T = objectMapper.readValue(this, T::class.java)

inline fun <reified T : ViewModel> Fragment.viewModel(): T =
    ViewModelProvider(this)[T::class.java]

// measureTime — stdlib
val (result, duration) = measureTimedValue {
    expensiveOperation()
}
```

## Key Rules
- Prefer `val` over `var`; immutability is the default
- Use `data class` for value objects; `sealed class` for algebraic types
- Scope functions: `let` for null checks, `apply` for builder patterns, `also` for side effects
- Avoid `!!` (non-null assertion) — use `?: throw`, `requireNotNull`, or safe navigation
- `companion object` is the Kotlin equivalent of Java static — don't abuse it for unrelated utilities
来源:skillsdirectory

评论0

登录后参与评论

还没有评论,来抢沙发吧