← Programming Core

KOTLIN CORE · 107

Syntax、Types、Functions:不要重學「程式設計」,而是重新映射概念

到這裡你已經知道 value、type、if、function、state。Kotlin 不是把這些概念重來一次;真正要學的是它如何用更嚴格的型別、expression 與 null-safety 語法表達同樣的程式問題。

Why now:Kotlin 在這個平台扮演什麼角色?

.kt source→ Kotlin compiler →bytecode / platform output→ JVM / Android Runtime →process / app

在 Android 路線裡,Kotlin source 通常不是像 Browser JavaScript 那樣直接下載後執行。它先經過 build toolchain,最後由 Android runtime 執行 app code。

Learning outcomes

1. val / var:控制的是 reference 能不能重新指定

val tripId = "trip-001"
// tripId = "trip-002" // compile error

var distanceKm = 0.0
distanceKm = 1.25

val 表示這個名稱之後不能指向另一個值;var 可以重新 assignment。

但不要誤解:val 不代表 object 內部一定 immutable。例如 val list = mutableListOf(1) 仍可以 list.add(2)。

2. Type inference 與 explicit types

val speed = 30.5          // inferred Double
val active = true         // inferred Boolean

val elapsedSeconds: Long = 120
val label: String = "Running"

和 TypeScript 一樣,不需要每個地方都重複寫 type。重要 boundary / public API / 容易誤解的型別才值得明確標示。

3. Function contract

fun calculateAverageSpeed(
    distanceKm: Double,
    elapsedSeconds: Long
): Double {
    if (elapsedSeconds == 0L) return 0.0

    val hours = elapsedSeconds / 3600.0
    return distanceKm / hours
}
arguments→ typed parameters →body→Double return value

4. if 在 Kotlin 是 expression

val status =
    if (distanceKm > 0.0) {
        "moving"
    } else {
        "idle"
    }

它不是只能做 control statement,也能直接產生一個 value。

5. when:把多分支規則集中表達

fun paceLabel(speedKmh: Double): String =
    when {
        speedKmh >= 80 -> "fast"
        speedKmh >= 40 -> "medium"
        speedKmh > 0 -> "slow"
        else -> "stopped"
    }

它很像更有表達力的多分支 expression。重點仍是規則順序與 boundary。

6. Project checkpoint:Trip Meter Domain Core v1

data class TripSnapshot(
    val distanceKm: Double,
    val elapsedSeconds: Long
)

fun averageSpeed(snapshot: TripSnapshot): Double {
    if (snapshot.elapsedSeconds == 0L) return 0.0

    val hours = snapshot.elapsedSeconds / 3600.0
    return snapshot.distanceKm / hours
}

fun statusOf(snapshot: TripSnapshot): String =
    when {
        snapshot.elapsedSeconds == 0L -> "ready"
        snapshot.distanceKm == 0.0 -> "waiting"
        else -> "moving"
    }

這個 domain core 還沒有 Android UI、GPS、permission。這是刻意的:先讓 business logic 可以脫離 platform 被理解與測試。

7. Debug evidence:compile error 和 business rule error

val elapsedSeconds: Long = "120"
// type mismatch:compile-time evidence
val hours = elapsedSeconds / 3600
// 若兩邊都是整數,會先做整數除法,可能造成 logic error

即使型別正確,運算規則仍可能錯;static typing 不是 logic correctness 的替代品。

Knowledge check

  1. val 和 object immutability 為什麼不是同一件事?
  2. 把 statusOf() 加入 "finished" 狀態,你需要新增哪個 input?
  3. 為什麼 domain logic 先不放 Activity / ViewModel 裡?
  4. 把一個 JavaScript function 改寫成 Kotlin,逐項對照 parameter / return / branch。