Delegasi dengan by
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Kotlin di Coddy. Pelajaran 46 dari 57.
Pendelegasian berarti sebuah object menyerahkan pekerjaan kepada object lain, alih-alih mewarisinya. Kotlin mendukungnya secara langsung: class Polite(private val inner: Greeter) : Greeter by inner mengimplementasikan Greeter dengan meneruskan setiap pemanggilan ke inner, dan class hanya menimpa bagian yang diubahnya:
interface Greeter {
fun hello(name: String): String
fun bye(name: String): String
}
class English : Greeter {
override fun hello(name: String) = "Hello, $name"
override fun bye(name: String) = "Bye, $name"
}
class Polite(private val inner: Greeter) : Greeter by inner {
override fun hello(name: String) = inner.hello(name) + ", pleased to meet you"
}Di dalam main:
val g = Polite(English())
println(g.hello("Ada"))
println(g.bye("Ada"))Output:
Hello, Ada, pleased to meet you
Bye, AdaDelegasi adalah alternatif untuk pewarisan. Delegasi bekerja dengan interface yang implementasinya bersifat final, dan delegate bisa berupa object apa pun yang dipilih saat program berjalan. Set ini menghitung setiap add dan meneruskan hal lainnya ke MutableSet biasa:
class CountingSet<T>(private val inner: MutableSet<T> = mutableSetOf()) : MutableSet<T> by inner {
var attempts = 0
private set
override fun add(element: T): Boolean {
attempts++
return inner.add(element)
}
}Di dalam main:
val tags = CountingSet<String>()
tags.add("kotlin")
tags.add("jvm")
tags.add("kotlin")
println("${tags.size} tags after ${tags.attempts} adds, contains jvm: ${"jvm" in tags}")Output:
2 tags after 3 adds, contains jvm: trueProperti yang didelegasikan menyerahkan getter dan setter suatu properti kepada object lain, sekali lagi dengan by. lazy dari bab 2 adalah salah satu delegate, dan map juga bisa menjadi delegate: setiap properti membaca entri dengan namanya sendiri:
class User(values: Map<String, Any?>) {
val name: String by values
val age: Int by values
}Di dalam main:
val u = User(mapOf("name" to "Ada", "age" to 36))
println("${u.name} is ${u.age}")Output:
Ada is 36Kamu bisa menulis delegate property sendiri: sebuah class dengan operator fun getValue, serta setValue untuk var. Kotlin memanggilnya setiap kali property dibaca atau ditulis. Delegate ini memangkas setiap teks yang ditetapkan dan menghitung perubahan:
import kotlin.reflect.KProperty
class Trimmed {
private var value = ""
var changes = 0
operator fun getValue(thisRef: Any?, property: KProperty<*>) = value
operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: String) {
value = newValue.trim()
changes++
}
}
class Form {
val nameField = Trimmed()
var name: String by nameField
}Di dalam main:
val form = Form()
form.name = " Ada "
form.name = "Ada L. "
println("[${form.name}] after ${form.nameField.changes} changes")Output:
[Ada L.] after 2 changesTantangan
MudahAntarmuka Storage (dengan put, get, dan keys) serta implementasinya, MapStorage, sudah disediakan. Tulis dua dekorator dengan delegasi class, masing-masing hanya meng-override put: LoggingStorage(inner) mencatat put a=1 dalam list log yang hanya bisa dibaca, lalu meneruskan pemanggilannya, sedangkan LimitedStorage(inner, max) menolak (mengembalikan false) penambahan key baru setelah ada max key, tetapi pembaruan key yang sudah ada tetap diizinkan. Semua hal lainnya diteruskan dengan by.
Kode yang disediakan membungkus MapStorage dengan LoggingStorage dan, jika baris pertama berisi batas positif, membungkusnya dengan LimitedStorage. Kode tersebut menjalankan perintah put a 1, get a, dan keys, lalu mencetak ok, refused, nilainya atau missing, dan daftar key, lalu mencetak log: put a=1, ....
Tulis kodemu di LoggingStorage.kt, LimitedStorage.kt, Storage.kt, dan MapStorage.kt. Main.kt berisi kode input/output yang disediakan dan tidak boleh diedit.
Coba sendiri
fun main() {
// Kode input/output yang disediakan: biarkan tetap seperti ini
val input = generateSequence(::readLine).toList()
val base = MapStorage()
val logging = LoggingStorage(base)
val limit = input[0].toInt()
val storage: Storage = if (limit > 0) LimitedStorage(logging, limit) else logging
for (cmd in input.drop(1)) {
val p = cmd.split(" ")
when (p[0]) {
"put" -> println(if (storage.put(p[1], p[2])) "ok" else "refused")
"get" -> println(storage.get(p[1]) ?: "missing")
else -> println(storage.keys())
}
}
println("log: " + logging.log.joinToString(", ").ifEmpty { "empty" })
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1class dan object
Bekerja dengan fileMendefinisikan classKonstruktor utamaBlok init dan validasiKonstruktor sekunderRingkasan: Kartu Perpustakaan2property dan Enkapsulasi
Accessor KustomModifier VisibilitasSetter Privatlazy dan lateinitRingkasan: Rekening Bank5Interface
Mendeklarasikan Interfacemethod DefaultBeberapa InterfaceInterface sebagai TipeUlasan: Metode Pembayaran11Proyek: Pengelolaan Perpustakaan
Buku dan AnggotaPeminjaman BukuLatihan sendiri: Playground Kotlin