Delegirane nekretnine u Kotlinu

1. Uvod

Programski jezik Kotlin ima izvornu podršku za svojstva klase.

Svojstva su obično podržana izravno odgovarajućim poljima, ali ne mora uvijek biti takvo - sve dok su ispravno izložena vanjskom svijetu, još uvijek se mogu smatrati svojstvima.

To se može postići rukovanjem ovim u geterima i postavljačima ili iskorištavanjem snage Delegati.

2. Što su delegirana svojstva?

Jednostavno rečeno, delegirana svojstva nisu podržana poljem klase i delegiranje dobivanja i postavljanja na drugi dio koda. To omogućuje apstrahiranje i dijeljenje delegirane funkcionalnosti između više sličnih svojstava - npr. spremanje vrijednosti svojstava na kartu umjesto u zasebna polja.

Delegirana svojstva koriste se deklariranjem svojstva i delegata koji koristi. The po ključna riječ označava da svojstvom upravlja dodijeljeni delegat umjesto vlastitog polja.

Na primjer:

klasa DelegateExample (karta: MutableMap) {var ime: Niz po mapi}

Ovdje se koristi činjenica da a Promjenjiva karta je sam delegat koji vam omogućuje da njegove ključeve tretirate kao svojstva.

3. Standardna delegirana svojstva

Standardna knjižnica Kotlin dolazi sa skupom standardnih delegata koji su spremni za upotrebu.

Već smo vidjeli primjer korištenja a Promjenjiva karta natrag na promjenjivo svojstvo. Na isti način možete vratiti nepromjenjivo svojstvo pomoću a Karta - omogućavanje pristupa pojedinačnim poljima kao svojstava, ali nikada njihovo mijenjanje.

The lijen delegat omogućuje izračunavanje vrijednosti svojstva samo pri prvom pristupu, a zatim u predmemoriju. Ovo može biti korisno za svojstva koja su možda skupa za izračunavanje i koja vam možda neće trebati - na primjer, učitavanje iz baze podataka:

class DatabaseBackedUser (userId: String) {ime vala: Niz lijenog {queryForValue ("ODABIRI ime OD korisnika WHERE userId =: userId", mapOf ("userId" to userId)}}

The uočljiv delegat omogućuje pokretanje lambde kad god se vrijednost svojstva promijeni, na primjer dopuštajući obavijesti o promjenama ili ažuriranje drugih srodnih svojstava:

class ObservaProperty {var name: String by Delegates.observable ("") {prop, old, new -> println ("Old value: $ old, New value: $ new")}}

Od Kotlina 1.4, također je moguće izravno prenijeti na drugu imovinu. Na primjer, ako preimenujemo svojstvo u API klasi, možemo ostaviti staro na mjestu i jednostavno delegirati novom:

klasa RenamedProperty {var newName: String = "" @Deprecated ("Umjesto toga koristi newName") ime var: String by this :: newName}

Ovdje, bilo kada pristupimo Ime imovine, učinkovito koristimo novoIme umjesto toga vlasništvo.

4. Stvaranje vaših delegata

Povremeno ćete htjeti napisati svoje delegate, umjesto da koristite one koji već postoje. Ovo se oslanja na pisanje klase koja proširuje jedno od dva sučelja - ReadOnlyProperty ili ReadWriteProperty.

Oba ova sučelja definiraju metodu koja se naziva getValue - koji se koristi za pružanje trenutne vrijednosti delegiranog svojstva kada se čita. To uzima dva argumenta i vraća vrijednost svojstva:

  • thisRef - referenca na klasu u kojoj se nalazi svojstvo
  • imovine - odraz opisa imovine koja se delegira

The ReadWriteProperty sučelje dodatno definira metodu koja se naziva setValue koja se koristi za ažuriranje trenutne vrijednosti svojstva kada je napisana. Ovo uzima tri argumenta i nema povratnu vrijednost:

  • thisRef - referenca na klasu u kojoj se nalazi svojstvo
  • imovine - Odraz opisa imovine koja se delegira
  • vrijednost - Nova vrijednost nekretnine

Od Kotlina 1.4, ReadWriteProperty sučelje se zapravo proširuje ReadOnlyProperty. To nam omogućuje da napišemo jednu izvedbenu klasu koja implementira ReadWriteProperty i upotrijebite ga za polja samo za čitanje unutar našeg koda. Prije bismo morali napisati dva različita delegata - jedan za polja samo za čitanje i drugi za promjenjiva polja.

Kao primjer, napišimo delegata koji uvijek radi u vezi s vezom baze podataka umjesto lokalnih polja:

class DatabaseDelegate (readQuery: String, writeQuery: String, id: Any): ReadWriteDelegate {fun getValue (thisRef: R, svojstvo: KProperty): T {return queryForValue (readQuery, mapOf ("id" to id))} fun setValue ( thisRef: R, svojstvo: KProperty, value: T) {update (writeQuery, mapOf ("id" to id, "value" to value))}}

To ovisi o dvije funkcije najviše razine za pristup bazi podataka:

  • queryForValue - ovo zahtijeva malo SQL-a i neke obveze i vraća prvu vrijednost
  • ažuriranje - za ovo je potreban neki SQL, a neki se veže i tretira ga kao UPDATE izraz

Tada to možemo koristiti kao bilo koji obični delegat i baza podataka treba automatski poduprijeti našu klasu:

class DatabaseUser (userId: String) {var name: String by DatabaseDelegate ("SELECT name FROM users WHERE userId =: id", "UPDATE users SET name =: value WHERE userId =: id", userId) var email: String by DatabaseDelegate ("ODABIRI e-poštu OD korisnika WHERE userId =: id", "AŽURIRAJ korisnika podešavaj email =: vrijednost WHERE userId =: id", userId)}

5. Delegiranje izrade delegata

Još jedna nova značajka koju imamo u Kotlinu 1.4 je sposobnost delegiranja izrade naših predavačkih klasa drugoj klasi. To djeluje primjenom PropertyDelegateProvider sučelje, koje ima jednu metodu za instanciju nečega što će se koristiti kao stvarni delegat.

To možemo koristiti za izvršavanje nekog koda oko stvaranja delegata koji će se koristiti - na primjer, za bilježenje onoga što se događa. Također ga možemo koristiti za dinamičko odabir delegata koji ćemo koristiti na temelju svojstva za koje se koristi. Na primjer, mogli bismo imati drugog delegata ako je svojstvo null:

klasa DatabaseDelegateProvider(readQuery: String, writeQuery: String, id: Bilo koji): PropertyDelegateProvider {nadjačati zabavu operatora provideDelegate (thisRef: T, prop: KProperty): ReadWriteDelegate {if (prop.returnType.isMarkedNullable) {return NullableDatabaseDelegate (readQuery, writeQuery, id)} else {return NonNullDatabaseDelegate (readQue}, idQ, readu}

To nam omogućuje da u svaki delegat napišemo jednostavniji kôd jer se oni moraju usredotočiti samo na ciljanije slučajeve. U navedenom to znamo NonNullDatabaseDelegate ikad će se koristiti samo na svojstvima koja ne mogu imati null vrijednost, pa nam za to nije potrebna dodatna logika.

6. Sažetak

Delegiranje svojstava moćna je tehnika koja vam omogućuje pisanje koda koji preuzima kontrolu nad drugim svojstvima i pomaže da se ova logika lako podijeli među različitim klasama. To omogućuje robusnu logiku za višekratnu upotrebu koja izgleda i osjeća se kao redoviti pristup nekretninama.

Potpuno radni primjer za ovaj članak možete pronaći na GitHubu.


$config[zx-auto] not found$config[zx-overlay] not found