Εξηγήστε πώς λειτουργεί η ανάθεση (delegation) στο Kotlin.
sobes.tech AI
Απάντηση από AI
Ο delegation στο Kotlin είναι ένας μηχανισμός που επιτρέπει σε ένα αντικείμενο να αναθέσει μέρος των ευθυνών του σε ένα άλλο αντικείμενο. Αυτό υλοποιείται χωρίς κληρονομικότητα, γεγονός που διευκολύνει πιο ευέλικτη σύνθεση.
Εφαρμόζεται για:
- επανάχρηση λειτουργικότητας.
- υλοποίηση του μοτίβου Delegation.
Το Kotlin υποστηρίζει delegation σε επίπεδο κλάσης και σε επίπεδο ιδιοτήτων.
Σε επίπεδο κλάσης:
Μια κλάση μπορεί να αναθέσει την υλοποίηση μιας διεπαφής σε ένα άλλο αντικείμενο με τη χρήση του τελεστή by. Αυτό αποφεύγει την ανάγκη χειροκίνητης επαναπροσδιορισμού όλων των μεθόδων της διεπαφής.
// Διεπαφή
interface Base {
fun printMessage()
fun printMessageLine()
}
// Κλάση-αντιπρόσωπος
class BaseImpl(val x: Int) : Base {
override fun printMessage() {
print(x)
}
override fun printMessageLine() {
println(x)
}
}
// Κλάση που αναθέτει την υλοποίηση
class Derived(b: Base) : Base by b
Σε επίπεδο ιδιοτήτων:
Η τιμή μιας ιδιότητας μπορεί να υπολογιστεί μέσω delegate. Αυτό επιτρέπει την υλοποίηση μοτίβων όπως η τε lazy αρχικοποίηση, παρατηρούμενες ιδιότητες και ιδιότητες με δυνατότητα αποθήκευσης σε τοπική αποθήκευση ροής.
Σύνταξη: val <propertyName>: <PropertyType> by <delegateExpression>.
Παραδείγματα ενσωματωμένων delegate ιδιοτήτων:
lazy: Για lazy αρχικοποίηση. Η τιμή υπολογίζεται μόνο κατά την πρώτη πρόσβαση στην ιδιότητα.val lazyValue: String by lazy { println("Υπολογισμός lazyValue") "Γειά" } fun main() { println(lazyValue) // "Υπολογισμός lazyValue" θα τυπωθεί μόνο εδώ println(lazyValue) // Η δεύτερη κλήση δεν θα προκαλέσει επαναυπολογισμό }Delegates.observable: Καλεί το καθορισμένο μπλοκ κώδικα κατά την αλλαγή της τιμής της ιδιότητας.import kotlin.properties.Delegates var name: String by Delegates.observable("<κανένα όνομα>") { prop, old, new -> println("$old -> $new") } fun main() { name = "Αλίσα" // <κανένα όνομα> -> Αλίσα name = "Μπομπ" // Αλίσα -> Μπομπ }Delegates.vetoable: Επιτρέπει την ακύρωση της ανάθεσης νέας τιμής αν δεν πληροίται μια συνθήκη.import kotlin.properties.Delegates var max: Int by Delegates.vetoable(0) { prop, old, new -> new > old } fun main() { println(max) // 0 max = 10 println(max) // 10 max = 5 // Δεν θα αλλάξει, επειδή 5 ≤ 10 println(max) // 10 }
Δημιουργία δικών σας delegate ιδιοτήτων:
Υλοποιούνται από τις διεπαφές ReadOnlyProperty ή ReadWriteProperty.
ReadOnlyProperty: Γιαvalιδιότητες. ΜέθοδοςgetValue.ReadWriteProperty: Γιαvarιδιότητες. ΜέθοδοιgetValueκαιsetValue.
import kotlin.reflect.KProperty
class ExampleDelegate {
var value: String = "Αρχική τιμή"
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
println("$thisRef, ευχαριστώ για την ανάθεση '${property.name}' σε εμένα!")
return value
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$thisRef, ευχαριστώ για την ειδοποίηση σχετικά με την ανάθεση '${property.name}' σε νέα τιμή '$value'")
this.value = value
}
}
class Container {
var myProp: String by ExampleDelegate()
}
fun main() {
val c = Container()
println(c.myProp) // Πρόσβαση στο getValue
c.myProp = "Νέα τιμή" // Πρόσβαση στο setValue
println(c.myProp)
}
Η ανάθεση διασφαλίζει την καθαρότητα του κώδικα, βελτιώνει την αναγνωσιμότητα και συμβάλλει στην εφαρμογή της αρχής DRY (Μην επαναλαμβάνεσαι).