Menu
CoddyTech

Hierarki Tersegel

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Kotlin di Coddy. Pelajaran 34 dari 57.

Class atau interface sealed memiliki kumpulan subclass langsung yang tertutup, semuanya dideklarasikan dalam package dan module yang sama. Compiler mengetahui semuanya, sehingga cocok untuk hasil dengan jumlah bentuk yang tetap:

sealed interface Result
data class Success(val value: Int) : Result
data class Failure(val reason: String) : Result

fun parseAge(text: String): Result {
    val n = text.toIntOrNull() ?: return Failure("not a number: $text")
    return if (n in 0..150) Success(n) else Failure("out of range: $n")
}

Di dalam main:

println(parseAge("42"))
println(parseAge("abc"))
println(parseAge("200"))

Output:

Success(value=42)
Failure(reason=not a number: abc)
Failure(reason=out of range: 200)

Karena set ini tertutup, when atas tipe tersegel bersifat lengkap tanpa else. Jika seseorang menambahkan subclass nanti, setiap when seperti itu tidak akan bisa dikompilasi sampai menangani kasus baru tersebut, sehingga tidak ada kasus yang terlupakan:

sealed interface Result
data class Success(val value: Int) : Result
data class Failure(val reason: String) : Result

fun describe(r: Result) = when (r) {
    is Success -> "ok: ${r.value}"
    is Failure -> "error: ${r.reason}"
}

Di dalam main:

println(describe(Success(7)))
println(describe(Failure("timeout")))

Output:

ok: 7
error: timeout

Case tanpa data adalah data object: satu instance dengan toString() yang dapat dibaca. Cabang when-nya tidak memerlukan is, karena hanya ada satu instance. Case lainnya dapat berupa data class, object, atau class biasa:

sealed interface Command
data object Quit : Command
data class Move(val steps: Int) : Command
data class Say(val text: String) : Command

fun parse(line: String): Command = when {
    line == "quit" -> Quit
    line.startsWith("move ") -> Move(line.drop(5).toInt())
    else -> Say(line)
}

fun run(c: Command) = when (c) {
    Quit -> "bye"
    is Move -> "moving ${c.steps}"
    is Say -> "saying ${c.text}"
}

Di dalam main:

for (line in listOf("move 3", "hello", "quit")) {
    val c = parse(line)
    println("$c: ${run(c)}")
}

Output:

Move(steps=3): moving 3
Say(text=hello): saying hello
Quit: bye

Enum atau hierarki tersegel? Enum adalah kumpulan tetap dari instans tunggal yang semuanya memiliki properti yang sama. Hierarki tersegel memungkinkan setiap kasus membawa datanya sendiri, dan kasus seperti Move dapat memiliki banyak instans dengan nilai yang berbeda:

enum class Light { RED, YELLOW, GREEN }          // bentuknya sama, masing-masing punya satu instance

sealed interface Payment                          // setiap kasus punya datanya sendiri
data class Card(val number: String) : Payment
data class Transfer(val iban: String, val reference: String) : Payment
data object Cash : Payment
challenge icon

Tantangan

Mudah

Robot memahami perintah dari sealed interface Command: Move(steps), Turn(left), Report, dan Invalid(text), yang sudah disediakan. Lengkapi parse(line): move 3 menghasilkan Move(3), turn left dan turn right menghasilkan Turn, report menghasilkan Report, dan apa pun selain itu, termasuk perintah move tanpa angka yang valid, menghasilkan Invalid dengan baris tersebut. Lalu lengkapi Robot.execute(command) dengan when yang mencakup semua kasus dan tanpa else. Robot mulai di (0, 0) menghadap N (utara adalah y + 1, timur adalah x + 1). Robot mengembalikan moved to (0, 3), facing W, at (0, 3) facing W, atau ignored.

Kode yang disediakan mengurai setiap baris dan mencetak Move(steps=3) -> moved to (0, 3).

Kodemu ditulis di Robot.kt, Parser.kt, Command.kt, Move.kt, Turn.kt, Report.kt, dan Invalid.kt. Main.kt berisi kode input/output yang disediakan dan tidak boleh diedit.

Coba sendiri

fun main() {
    // Kode input/output yang disediakan: biarkan apa adanya
    val input = generateSequence(::readLine).toList()
    val robot = Robot()
    for (line in input) {
        val command = parse(line)
        println("$command -> ${robot.execute(command)}")
    }
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Playground Kotlin