Menu
Coddy logo textTech

Mühürlü Hiyerarşiler

Coddy'nin Kotlin Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 34 / 57.

sealed sınıfı veya arayüzü, tamamı aynı paket ve modülde tanımlanmış, doğrudan alt sınıflardan oluşan kapalı bir kümeye sahiptir. Derleyici bunların her birini bilir; bu da sabit sayıda biçime sahip sonuçlar için uygundur:

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")
}

main içinde:

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

Çıktı:

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

Küme kapalı olduğundan, mühürlü bir tür üzerindeki when, else olmadan tüm durumları kapsar. Birisi daha sonra bir alt sınıf eklerse, bu tür her when ifadesi yeni durumu ele alana kadar derlenmeyi durdurur; böylece hiçbir durum unutulmaz:

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}"
}

main içinde:

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

Çıktı:

ok: 7
error: timeout

Veri içermeyen bir durum, data object’tir: okunabilir bir toString() işlevine sahip tek bir örnek. when dalı için is gerekmez, çünkü yalnızca bir örnek vardır. Diğer durumlar veri sınıfları, nesneler veya sıradan sınıflar olabilir:

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}"
}

main içinde:

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

Çıktı:

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

Enum mu yoksa sealed hiyerarşi mi? Enum, hepsi aynı özelliklere sahip olan sabit bir tekil örnekler kümesidir. Sealed hiyerarşi, her durumun kendi verisini taşımasına olanak tanır ve Move gibi bir durum, farklı değerlere sahip birçok örneğe sahip olabilir:

enum class Light { RED, YELLOW, GREEN }          // aynı şekil, her birinden bir örnek

sealed interface Payment                          // her durumun kendi verisi var
data class Card(val number: String) : Payment
data class Transfer(val iban: String, val reference: String) : Payment
data object Cash : Payment
challenge icon

Görev

Kolay

Bir robot, sağlanan sealed interface Command'ın komutlarını anlar: Move(steps), Turn(left), Report ve Invalid(text). parse(line) işlevini tamamlayın: move 3, Move(3) verir; turn left ve turn right, Turn verir; report, Report verir; geçerli bir sayı olmadan yapılan bir hareket de dâhil olmak üzere diğer her şey, satırla birlikte Invalid verir. Ardından Robot.execute(command) işlevini, kapsamlı bir when ve else olmadan tamamlayın. Robot (0, 0) konumunda, N yönüne bakarak başlar (kuzey y + 1, doğu x + 1 yönündedir). moved to (0, 3), facing W, at (0, 3) facing W veya ignored döndürür.

Sağlanan kod her satırı ayrıştırır ve Move(steps=3) -> moved to (0, 3) yazdırır.

Kodunuz Robot.kt, Parser.kt, Command.kt, Move.kt, Turn.kt, Report.kt ve Invalid.kt dosyalarına gelir. Main.kt, sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

fun main() {
    // Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
    val input = generateSequence(::readLine).toList()
    val robot = Robot()
    for (line in input) {
        val command = parse(line)
        println("$command -> ${robot.execute(command)}")
    }
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Kotlin playground