Vodič za Kotlin sučelja

1. Pregled

U ovom vodiču, razgovarat ćemo o tome kako definirati i implementirati sučelja u Kotlinu.

Također ćemo pogledati kako klasa može implementirati više sučelja. To sigurno može uzrokovati sukobe, a mi ćemo naučiti mehanizam koji Kotlin mora riješiti.

2. Sučelja u Kotlinu

Sučelje je način davanja opisa ili ugovora za klase u objektno orijentiranom programiranju. Mogu sadržavati svojstva i funkcije na apstraktan ili konkretan način, ovisno o programskom jeziku. Provest ćemo detalje o sučeljima u Kotlinu.

Sučelja u Kotlinu slična su sučeljima u mnogim drugim jezicima poput Jave. Ali oni imaju specifičnu sintaksu, pregledajmo ih u sljedećih nekoliko pododjeljaka.

2.1. Definiranje sučelja

Počnimo s definiranjem našeg prvog sučelja u Kotlinu:

sučelje SimpleInterface

Ovo je najjednostavnije sučelje koje je potpuno prazno. Oni su također poznati kao sučelja markera.

Dodajmo sada neke funkcije našem sučelju:

sučelje SimpleInterface {fun firstMethod (): String fun secondMethod (): String {return ("Hello, World!")}}

U prethodno definirano sučelje dodali smo dvije metode:

  • Jedan od njih nazvao je firstMethod je apstraktna metoda
  • Dok je druga zvala secondMethod ima zadanu implementaciju.

Idemo naprijed i dodajte neka svojstva našem sučelju sada:

sučelje SimpleInterface {val firstProp: String val secondProp: String get () = "Drugo svojstvo" fun firstMethod (): String fun secondMethod (): String {return ("Hello, from:" + secondProp)}}

Ovdje smo našem sučelju dodali dva svojstva:

  • Nazvao je jedan od njih firstProp je tipa String i apstraktan je
  • Nazvao je drugi secondProp je također tipa string, ali definira implementaciju za njegovog pristupnika.

Imajte na umu da svojstva u sučelju ne mogu održavati stanje. Dakle, sljedeće je ilegalni izraz u Kotlinu:

sučelje SimpleInterface {val firstProp: String = "Prvo svojstvo" // Ilegalna deklaracija}

2.2. Implementacija sučelja

Sad kad smo definirali osnovno sučelje, pogledajmo kako to možemo primijeniti u klasi u Kotlinu:

class SimpleClass: SimpleInterface {override val firstProp: String = "First Property" override fun firstMethod (): String {return ("Hello, from:" + firstProp)}}

Imajte na umu da kad definiramo SimpleClass kao provedba Jednostavno sučelje, moramo osigurati samo implementaciju apstraktnih svojstava i funkcija. Međutim, mi može nadjačati bilo koje prethodno definirano svojstvo ili funkciju.

Zamijenimo sada sva prethodno definirana svojstva i funkcije u našoj klasi:

klasa SimpleClass: SimpleInterface {override val firstProp: String = "First Property" override val secondProp: String get () = "Second Property, Overridden!" nadjačati zabavu firstMethod (): String {return ("Hello, from:" + firstProp)} override fun secondMethod (): String {return ("Hello, from:" + secondProp + firstProp)}}

Evo, nadjačali smo imovinu secondProp i funkcija secondFunction koji su prethodno bili definirani u sučelju Jednostavno sučelje.

2.3 Implementacija sučelja putem delegiranja

Delegiranje je obrazac dizajna u objektno orijentiranom programiranju kako bi se postigla ponovna upotrebljivost koda kroz kompoziciju umjesto nasljeđivanjem. Iako je to moguće implementirati na mnogim jezicima, poput Jave, Kotlin ima domaću podršku za provedbu putem delegiranja.

Ako započnemo s osnovnim sučeljem i klasom:

sučelje MyInterface {fun someMethod (): String} class MyClass (): MyInterface {override fun someMethod (): String {return ("Hello, World!")}}

Zasad ništa novo. Ali sada možemo definirati drugu klasu koja se provodi MyInterface putem delegiranja:

klasa MyDerivedClass (myInterface: MyInterface): MyInterface by myInterface

MyDerivedClass očekuje delegata kao argument koji zapravo implementira sučelje MyInterface.

Pogledajmo kako možemo pozvati funkciju sučelja putem delegata:

val myClass = MyClass () MyDerivedClass (myClass) .someMethod ()

Ovdje smo napravili instanciju Moj razred i koristio ga kao delegata za pozivanje funkcija sučelja na MyDerivedClass, koja zapravo nikada nije izravno implementirala ove funkcije.

3. Višestruko nasljeđivanje

Višestruko nasljeđivanje ključni je pojam u paradigmi objektno orijentiranog programiranja. To omogućuje klasi da naslijedi karakteristike iz više od jednog roditeljskog objekta, poput sučelja, na primjer.

Iako ovo pruža veću fleksibilnost u objektnom modeliranju, ono dolazi s vlastitim nizom složenosti. Jedan od takvih je "problem s dijamantima".

Java 8 ima vlastite mehanizme za rješavanje problema s dijamantima, kao i bilo koji drugi jezik koji omogućava višestruko nasljeđivanje.

Pogledajmo kako se Kotlin tome obraća putem sučelja.

3.1. Nasljeđivanje više sučelja

Počet ćemo definiranjem dva jednostavna sučelja:

sučelje FirstInterface {fun someMethod (): String fun fun anotherMethod (): String {return ("Hello, from anotherMethod in FirstInterface")}} interface InterInterface {fun someMethod (): String {return ("Hello, from someMethod in SecondInterface") } zabava anotherMethod (): String {return ("Pozdrav, iz anotherMethod u SecondInterface")}}

Imajte na umu da oba sučelja imaju metode s istim ugovorom.

Sada definirajmo klasu koja nasljeđuje oba ova sučelja:

klasa SomeClass: FirstInterface, SecondInterface {override fun someMethod (): String {return ("Hello, from someMethod in SomeClass")} override fun anotherMethod (): String {return ("Hello, from anotherMethod in SomeClass")}}

Kao što vidimo, Neka klasa provodi oboje Prvo sučelje i SecondInterface. Iako je sintaktički ovo prilično jednostavno, ovdje postoji malo semantike koja zahtijeva pažnju. O ovome ćemo govoriti u sljedećem pododjeljku.

3.2. Rješavanje sukoba

Kada implementira više sučelja, klasa može naslijediti funkciju koja ima zadanu implementaciju za isti ugovor u više sučelja. To postavlja problem pozivanja ove funkcije iz instance izvedbene klase.

Da bi razriješio ovaj sukob, Kotlin zahtijeva da potklasa osigura nadjačanu provedbu takvih funkcija kako bi rezolucija bila eksplicitna.

Na primjer, Neka klasa gore provodi drugiMetoda. Ali, da nije, Kotlin ne bi znao hoće li se pozivati Prvi ili SecondInterface's zadana implementacija drugiMetoda. Neka klasa mora provesti drugiMetoda zbog ovog razloga.

Međutim, someMethod je malo drugačija jer zapravo nema sukoba. Prvo sučelje ne pruža zadanu implementaciju za someMethod. To je reklo, Neka klasa još uvijek to mora provesti jer Kotlin nas prisiljava da implementiramo sve naslijeđene funkcije, bez obzira jesu li definirane jednom ili više puta u nadređenim sučeljima.

3.3. Rješavanje problema s dijamantom

"Dijamantni problem" pojavljuje se kada dva podređena objekta osnovnog objekta opisuju određeno ponašanje definirano osnovnim objektom. Sada objekt koji nasljeđuje oba ova podređena objekta mora riješiti na koje naslijeđeno ponašanje se pretplaćuje.

Kotlinovo rješenje ovog problema je kroz pravila definirana za višestruko nasljeđivanje u prethodnom pododjeljku. Definirajmo nekoliko sučelja i izvedbenu klasu koja će predstaviti problem s dijamantima:

sučelje BaseInterface {fun someMethod (): String} sučelje FirstChildInterface: BaseInterface {override fun someMethod (): String {return ("Hello, from someMethod in FirstChildInterface")}} interface SecondChildInterface: BaseInterface {override fun someMethod (): String {return ("Pozdrav, iz someMethod u SecondChildInterface")}} klasa ChildClass: FirstChildInterface, SecondChildInterface {nadjačati zabavu someMethod (): String {return super.someMethod ()}}

Ovdje smo definirali BaseInterface koja je proglasila apstraktnu funkciju tzv someMethod. Oba sučelja FirstChildInterface i SecondChildInterface nasljeđuje od BaseInterface i implementirati funkciju someMethod.

Sada dok provodimo ChildClass nasljeđujući od FirstChildInterface i SecondChildInterface, potrebno je da nadjačamo funkciju someMethod. Međutim, iako moramo nadjačati metodu, još uvijek možemo jednostavno nazvati super kao radimo ovdje sa SecondChildInterface.

4. Sučelja u usporedbi s apstraktnim klasama u Kotlinu

Apstraktna nastava u Kotlinu je klase koje se ne mogu instancirati. To može sadržavati jedno ili više svojstava i funkcija. Ta svojstva i funkcije mogu biti apstraktne ili konkretne. Svaka klasa koja nasljeđuje apstraktnu klasu mora implementirati sva naslijeđena apstraktna svojstva i funkcije, osim ako sama ta klasa također nije deklarirana kao apstraktna.

4.1. Razlike između sučelja i apstraktne klase

Čekati! Ne zvuči li to točno kao ono što čini sučelje?

Zapravo se na početku apstraktna klasa ne razlikuje mnogo od sučelja. Ali, postoje suptilne razlike koje upravljaju odabirom koji donosimo:

  • Predavanja u Kotlinu mogu implementirati onoliko sučelja koliko žele, ali mogu se proširiti samo iz jedne apstraktne klase
  • Svojstva u sučelju ne mogu održavati stanje, dok to mogu u apstraktnoj klasi

4.2. Kada bismo trebali što koristiti?

Sučelje je samo nacrt za definiranje klasa, oni po želji mogu imati i neke zadane implementacije. S druge strane, apstraktna klasa je nepotpuna implementacija koju dovršavaju produžujuće klase.

Tipično za definiranje ugovora treba koristiti sučelja, što izaziva mogućnosti koje obećava pružiti. Provedbena klasa snosi odgovornost za ispunjenje tih obećanja. An apstraktnu klasu, međutim, treba koristiti za dijeljenje djelomičnih karakteristika s proširenim klasama. Proširujući tečaj može ga dalje dovršiti.

5. Usporedba s Java sučeljima

Izmjenama Java sučelja u Javi 8, vrlo su se približili Kotlinovim sučeljima. Jedan od naših prethodnih članaka bilježi nove značajke predstavljene u Javi 8, uključujući promjene na sučelju.

Sada postoje uglavnom sintaktičke razlike između sučelja Java i Kotlin. Jedna razlika koja se ističe povezana je s ključnom riječi "nadjačati". U Kotlinu, dok implementiramo apstraktna svojstva ili funkcije naslijeđene od sučelja, obavezno ih je kvalificirati ključnom riječi „nadjačati“. U Javi ne postoji takav izričiti zahtjev.

6. Zaključak

U ovom vodiču razgovarali smo o Kotlinovim sučeljima, kako ih definirati i implementirati. Tada smo razgovarali o nasljeđivanju s više sučelja i sukobu koji oni mogu stvoriti. Pogledali smo kako se Kotlin nosi s takvim sukobima.

Na kraju smo razgovarali o sučeljima u usporedbi sa apstraktnim klasama u Kotlinu. Također smo ukratko razgovarali o tome kako se sučelje Kotlin uspoređuje s Java sučeljem.

Kao i uvijek, kod za primjere dostupan je na GitHub-u.


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