0Pricing
Kotlin Academy · บทเรียน

when แบบครอบคลุมทุกกรณีกับลำดับชั้น Sealed

เขียนนิพจน์ when ที่ครอบคลุม sealed ทุกรูปแบบอย่างครบถ้วน

when แบบครอบคลุมทุกกรณีกับลำดับชั้น Sealed เป็นบทเรียน Kotlin Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Kotlin Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน

นิพจน์เงื่อนไขที่ครอบคลุมทุกกรณี

นิพจน์ when ที่ใช้เป็นนิพจน์ต้อง ครอบคลุมทุกกรณี ซึ่งหมายถึงต้องจัดการค่าที่เป็นไปได้ทุกค่า ลำดับชั้นแบบปิดผนึกช่วยให้คอมไพเลอร์ตรวจสอบสิ่งนี้แทนคุณได้

นิพจน์เงื่อนไขที่ไม่ครอบคลุมบนชนิดเปิด

สำหรับคลาสทั่วไป คอมไพเลอร์ไม่สามารถตรวจสอบชนิดย่อยทั้งหมดได้ จึงต้องมีแขนง else

open class Shape
class Circle : Shape()
class Square : Shape()
fun describe(s: Shape) = when (s) {
    is Circle -> "circle"
    is Square -> "square"
    else      -> "unknown" // required
}
fun main() { println(describe(Circle())) }

นิพจน์เงื่อนไขที่ครอบคลุมบนชนิดแบบปิดผนึก

สำหรับคลาสแบบปิดผนึก คอมไพเลอร์ทราบชนิดย่อยทั้งหมด หากครอบคลุมทุกกรณีแล้ว ก็ไม่จำเป็นต้องใช้ else

sealed class Result
class Success(val value: Int) : Result()
class Failure(val msg: String) : Result()
fun describe(r: Result) = when (r) {
    is Success -> "ok: ${r.value}"
    is Failure -> "err: ${r.msg}"
}
fun main() {
    println(describe(Success(42)))
    println(describe(Failure("nope")))
}

อินเทอร์เฟซแบบปิดผนึก

อินเทอร์เฟซแบบปิดผนึกช่วยให้ตรวจสอบความครอบคลุมได้ครบถ้วน แม้คลาสจะต้องสืบทอดหลายทาง

sealed interface Animal
class Dog : Animal
class Cat : Animal
fun speak(a: Animal) = when (a) {
    is Dog -> "woof"
    is Cat -> "meow"
}
fun main() {
    println(speak(Dog()))
    println(speak(Cat()))
}

การแปลงประเภทอัจฉริยะในแขนงเงื่อนไข

ภายในแต่ละแขนง is Kotlin จะเปลี่ยนชนิดของตัวแปรเป็นชนิดเฉพาะให้โดยอัตโนมัติ จึงไม่ต้องแปลงชนิดด้วยตนเอง

sealed class Event
data class Click(val x: Int, val y: Int) : Event()
data class Key(val char: Char) : Event()
fun handle(e: Event) = when (e) {
    is Click -> "clicked at (${e.x},${e.y})" // smart-cast
    is Key   -> "key=${e.char}"
}
fun main() {
    println(handle(Click(10, 20)))
    println(handle(Key('A')))
}

การลืมกรณีหนึ่ง

หากเพิ่มรูปแบบใหม่ในภายหลัง นิพจน์ when ที่ครอบคลุมทุกกรณีและยังใช้ชนิดแบบปิดผนึกเป็นนิพจน์จะคอมไพล์ไม่ผ่าน นี่คือกลไกช่วยเพิ่มความปลอดภัยที่ยอดเยี่ยม

sealed class Status
object Idle : Status()
object Running : Status()
// If we add object Done : Status(), every exhaustive when must update.
fun text(s: Status): String = when (s) {
    is Idle -> "idle"
    is Running -> "running"
}
fun main() { println(text(Idle)) }

ชนิดแบบปิดผนึกกับคลาสข้อมูล

รูปแบบที่ใช้บ่อยคือการใช้คลาสข้อมูลเป็นรูปแบบต่าง ๆ ในลำดับชั้นแบบปิดผนึก

sealed class UiState {
    object Loading : UiState()
    data class Success(val data: List<String>) : UiState()
    data class Error(val message: String) : UiState()
}
fun render(state: UiState) = when (state) {
    UiState.Loading -> "loading..."
    is UiState.Success -> "got ${state.data.size} items"
    is UiState.Error -> "error: ${state.message}"
}
fun main() {
    println(render(UiState.Loading))
    println(render(UiState.Success(listOf("a", "b"))))
    println(render(UiState.Error("404")))
}

การใช้ when เป็นคำสั่ง

เมื่อใช้ when เป็นคำสั่ง (ไม่ใช่นิพจน์) ก็ไม่จำเป็นต้องครอบคลุมทุกกรณี แต่คุณจะสูญเสียกลไกช่วยเพิ่มความปลอดภัยนี้

sealed class Cmd
object Start : Cmd()
object Stop : Cmd()
fun execute(c: Cmd) {
    // Statement form: no error if incomplete (avoid this style)
    when (c) {
        Start -> println("started")
        Stop -> println("stopped")
    }
}
fun main() { execute(Start); execute(Stop) }

บังคับตรวจสอบความครอบคลุมของคำสั่ง

กำหนดค่าให้กับ when (หรือใช้เทคนิค .exhaustive) เพื่อให้คอมไพเลอร์บังคับให้ครอบคลุมทุกกรณี

sealed class Cmd
object Start : Cmd()
object Stop : Cmd()
fun execute(c: Cmd) {
    val handled: Unit = when (c) { // expression context now
        Start -> println("started")
        Stop -> println("stopped")
    }
}
fun main() { execute(Start) }

แขนงหลายกรณี

จัดกลุ่มกรณีด้วยเครื่องหมายจุลภาค เพื่อใช้เนื้อหาของแขนงร่วมกันกับหลายรูปแบบ

sealed class Event
class Click : Event()
class Tap : Event()
class Drag : Event()
fun isPointer(e: Event) = when (e) {
    is Click, is Tap, is Drag -> true
}
fun main() { println(isPointer(Tap())) }

ชนิดแบบปิดผนึกซ้อนกัน

ลำดับชั้นแบบปิดผนึกสามารถซ้อนกันได้ และการตรวจสอบความครอบคลุมยังทำงานกับต้นไม้ที่มีหลายระดับ

sealed class Network {
    sealed class Wifi : Network() {
        object Open : Wifi()
        data class Secured(val ssid: String) : Wifi()
    }
    object Cellular : Network()
}
fun describe(n: Network) = when (n) {
    Network.Wifi.Open -> "open wifi"
    is Network.Wifi.Secured -> "secured: ${n.ssid}"
    Network.Cellular -> "cellular"
}
fun main() {
    println(describe(Network.Wifi.Secured("home")))
    println(describe(Network.Cellular))
}

ตรวจสอบอย่างรวดเร็ว

ประโยชน์หลักของการใช้ when กับลำดับชั้นแบบปิดผนึกคืออะไร

ทบทวน

ใช้คลาสหรืออินเทอร์เฟซแบบปิดผนึกร่วมกับ when เพื่อตรวจสอบความครอบคลุมตั้งแต่เวลาคอมไพล์ การแปลงประเภทอัจฉริยะช่วยให้เนื้อหาในแขนงต่าง ๆ เรียบง่าย ใช้เป็นนิพจน์ (หรือกำหนดผลลัพธ์ให้ตัวแปร) เพื่อบังคับการตรวจสอบ จัดกลุ่มกรณีด้วยเครื่องหมายจุลภาค และซ้อนชนิดแบบปิดผนึกเพื่อสร้างสถานะรูปต้นไม้

คำถามที่พบบ่อย

บทเรียน “when แบบครอบคลุมทุกกรณีกับลำดับชั้น Sealed” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “when แบบครอบคลุมทุกกรณีกับลำดับชั้น Sealed” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Kotlin Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “when แบบครอบคลุมทุกกรณีกับลำดับชั้น Sealed”

เขียนนิพจน์ when ที่ครอบคลุม sealed ทุกรูปแบบอย่างครบถ้วน คุณปฏิบัติ Kotlin Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Kotlin Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Kotlin Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “when แบบครอบคลุมทุกกรณีกับลำดับชั้น Sealed” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Kotlin Academy นี้ได้ไหม

ได้ บทเรียน Kotlin Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. sealed class กับ sealed interface: ควรใช้แบบใด
  2. when แบบครอบคลุมทุกกรณีกับลำดับชั้น Sealed
  3. จำลองสถานะ UI ด้วย Sealed Class
  4. การซ้อนและรวมลำดับชั้น Sealed
← กลับไปที่ Kotlin Academy