Útmutató a Kotlin interfészekhez

1. Áttekintés

Ebben az oktatóanyagban megbeszéljük az interfészek meghatározását és megvalósítását Kotlinban.

Megvizsgáljuk azt is, hogy egy osztály hogyan valósíthat meg több interfészt. Ez minden bizonnyal konfliktusokat okozhat, és megismerjük azt a mechanizmust, amelyet Kotlinnak meg kell oldania.

2. Interfészek Kotlinban

Az interfész az objektum-orientált programozás osztályainak leírását vagy szerződését nyújtja. A programozási nyelvtől függően elvont vagy konkrét módon tartalmazhatnak tulajdonságokat és funkciókat. Átnézzük a Kotlin-i interfészek részleteit.

Az interfészek Kotlinban hasonlóak sok más nyelv interfészéhez, például a Java-hoz. De sajátos szintaxisuk van, nézzük át őket a következő néhány alfejezetben.

2.1. Interfészek meghatározása

Kezdjük azzal, hogy meghatározzuk az első felületünket Kotlinban:

interfész SimpleInterface

Ez a legegyszerűbb felület, amely teljesen üres. Ezeket marker interfészeknek is nevezik.

Vegyünk fel néhány funkciót a felületünkre:

felület SimpleInterface {fun firstMethod (): String fun secondMethod (): String {return ("Hello, Világ!")}}

Két módszert adtunk a korábban definiált felületünkhöz:

  • Egyikük f-nek hívtairstMethod egy elvont módszer
  • Míg a másik hívta secondMethod alapértelmezett megvalósítással rendelkezik.

Folytassuk, és most adjunk hozzá néhány tulajdonságot a felületünkhöz:

felület SimpleInterface {val firstProp: String val secondProp: String get () = "Második tulajdonság" fun firstMethod (): String fun secondMethod (): String {return ("Hello, from:" + secondProp)}}

Itt két tulajdonságot adtunk a felületünkhöz:

  • Egyikük telefonált firstProp String típusú és absztrakt
  • A második hívott secondProp szintén a string karakterlánc, de meghatároz egy megvalósítást az elérőjéhez.

Vegye figyelembe, hogy egy interfész tulajdonságai nem tudják fenntartani az állapotot. Tehát a következő illegális kifejezés Kotlinban:

interfész SimpleInterface {val firstProp: String = "Első tulajdonság" // Illegális nyilatkozat}

2.2. Interfészek megvalósítása

Most, hogy meghatároztunk egy alapfelületet, nézzük meg, hogyan tudjuk ezt megvalósítani egy Kotlin-osztályban:

osztály SimpleClass: SimpleInterface {felülbírálja val firstProp: String = "Az első tulajdonság" felülbírálja a fun firstMethod (): String {return ("Hello, from:" + firstProp)}}

Vegye figyelembe, hogy amikor meghatározzuk SimpleClass megvalósításaként SimpleInterface, csak az elvont tulajdonságok és függvények megvalósítását kell biztosítanunk. Mi azonban felülírhat bármely korábban definiált tulajdonságot vagy funkciót is.

Most írjuk felül az osztályunk összes korábban definiált tulajdonságát és függvényét:

osztály SimpleClass: SimpleInterface {felülbírálja val firstProp: String = "Első tulajdonság" felülbírálja val secondProp: String get () = "Második tulajdonság, felülbírálva!" felülírja a fun firstMethod (): String {return ("Hello, from:" + firstProp)} felülírja a fun secondMethod (): String {return ("Hello, from:" + secondProp + firstProp)}}

Itt felülírtuk az ingatlant secondProp és a függvény secondFunction amelyeket korábban az interfészen definiáltak SimpleInterface.

2.3 Interfészek megvalósítása átruházással

A delegálás az objektum-orientált programozás mintája hogy a kód újrafelhasználhatóságát öröklés helyett kompozícióval érjék el. Bár ez sok nyelven megvalósítható, például a Java-ban, Kotlin natív támogatást nyújt a megvalósításhoz delegálás útján.

Ha egy alap interfésszel és osztállyal kezdjük:

felület MyInterface {fun someMethod (): String} osztály MyClass (): MyInterface {felülbírálja a fun someMethod (): String {return ("Hello, világ!")}}

Eddig semmi új. De most meghatározhatunk egy másik osztályt, amely megvalósul MyInterface delegálás útján:

class MyDerivedClass (myInterface: MyInterface): MyInterface by myInterface

MyDerivedClass a felhatalmazót olyan érvként várja, amely ténylegesen megvalósítja az interfészt MyInterface.

Nézzük meg, hogyan hívhatjuk meg a felület egy funkcióját a delegálton keresztül:

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

Itt példányosítottunk Az osztályom és ezt használta felhatalmazottként az interfész funkcióinak meghívására MyDerivedClass, amelyek valójában soha nem valósították meg ezeket a funkciókat közvetlenül.

3. Többszörös öröklés

A többszörös öröklés kulcsfontosságú fogalom az objektum-orientált programozási paradigmában. Ez lehetővé teszi, hogy egy osztály több szülőobjektumból örökölje a jellemzőket, például egy interfészről.

Ez ugyan nagyobb rugalmasságot biztosít az objektummodellezésben, de saját bonyolultsággal rendelkezik. Ilyen például a „gyémántprobléma”.

A Java 8 saját mechanizmusokkal rendelkezik a gyémántprobléma kezelésére, csakúgy, mint bármely más, többszörös öröklést lehetővé tevő nyelv.

Lássuk, hogyan kezeli Kotlin az interfészeken keresztül.

3.1. Több interfész öröklése

Először két egyszerű interfészt határozunk meg:

felület FirstInterface {fun someMethod (): String fun anotherMethod (): String {return ("Hello, from anotherMethod in FirstInterface")}}} interface SecondInterface {fun someMethod (): String {return ("Hello, from someMethod in SecondInterface") } fun anotherMethod (): String {return ("Hello, from AnotherMethod in SecondInterface")}}

Vegye figyelembe, hogy mindkét interfésznek ugyanazzal a szerződéssel vannak metódusai.

Most definiáljunk egy osztályt, amely örökli mindkét interfészt:

class SomeClass: FirstInterface, SecondInterface {override fun someMethod (): String {return ("Hello, from someMethod in SomeClass")}} felülírja a fun funMethod (): String {return ("Hello, egy másik metódust a SomeClass-ban")}}

Ahogy látjuk, SomeClass megvalósítja mindkettőt FirstInterface és SecondInterface. Míg szintaktikailag ez meglehetősen egyszerű, van itt egy kis szemantika, amely figyelmet igényel. Ezt a következő alfejezetben fogjuk áttekinteni.

3.2. Konfliktusok megoldása

Több interfész megvalósításakor egy osztály örökölhet egy olyan funkciót, amelynek alapértelmezett megvalósítása van ugyanazon szerződéshez több interfészben. Ez felveti a függvény meghívásának problémáját az implementációs osztály egyik példányától.

A konfliktus megoldásához Kotlin megköveteli, hogy az alosztály biztosítsa az ilyen funkciók felülbírálását, hogy a megoldás egyértelmű legyen.

Például, SomeClass fenti eszközöket másikMódszer. De ha nem így lenne, Kotlin nem tudná, hivatkozhat-e rá Első vagy SecondInterface's alapértelmezett megvalósítása másikMódszer. SomeClass végre kell hajtania másikMódszer emiatt.

Azonban, someMethod egy kicsit más, mivel valójában nincs konfliktus. FirstInterface nem nyújt alapértelmezett megvalósítást a someMethod. Hogy az említett, SomeClass még mindig végre kell hajtania, mert Kotlin arra kényszerít minket, hogy minden öröklődő funkciót hajtsunk végre, függetlenül attól, hogy ezeket egyszer vagy többször definiálták-e a szülői interfészek.

3.3. A gyémántprobléma megoldása

„Gyémántprobléma” akkor fordul elő, amikor egy alapobjektum két gyermekobjektuma leírja az alapobjektum által meghatározott sajátos viselkedést. Most egy mindkét gyermekobjektumtól örökölt objektumnak meg kell oldania, hogy mely öröklött viselkedésre iratkozik fel.

Kotlin megoldást ad erre a problémára a többszörös öröklődésre az előző alfejezetben meghatározott szabályok révén. Definiáljunk néhány interfészt és egy megvalósítási osztályt a gyémántprobléma bemutatásához:

interfész BaseInterface {fun someMethod (): String} felület FirstChildInterface: BaseInterface {override fun someMethod (): String {return ("Hello, from someMethod in FirstChildInterface")}}} interfész SecondChildInterface: BaseInterface {override fun someMethod (): String {return ("Hello, from someMethod in SecondChildInterface")}} class ChildClass: FirstChildInterface, SecondChildInterface {override fun someMethod (): String {return super.someMethod ()}}

Itt definiáltuk BaseInterface amely egy absztrakt függvényt deklarált someMethod. Mindkét interfész FirstChildInterface és SecondChildInterface örököl BaseInterface és hajtsa végre a funkciót someMethod.

Most, amikor megvalósítjuk ChildClass örökölni FirstChildInterface és SecondChildInterface, szükséges, hogy felülírjuk a függvényt someMethod. Azonban, annak ellenére, hogy felül kell írnunk a módszert, mégis egyszerűen hívhatunk szuper mint itt csináljuk SecondChildInterface.

4. Interfészek a Kotlin-i absztrakt osztályokkal összehasonlítva

Absztrakt osztályok Kotlinban vannak osztályok, amelyek nem példányosíthatók. Ez egy vagy több tulajdonságot és funkciót tartalmazhat. Ezek a tulajdonságok és funkciók lehetnek absztrakt vagy konkrétak. Bármely absztrakt osztályból örökölt osztálynak meg kell valósítania az összes örökölt absztrakt tulajdonságot és funkciót, kivéve, ha maga az osztály is absztraktnak van nyilvánítva.

4.1. Az interfész és az absztrakt osztály közötti különbségek

Várjon! Ez nem pontosan úgy hangzik, mint egy felület?

Valójában a kezdetek kezdetén egy absztrakt osztály nem nagyon különbözik az interfésztől. De vannak finom különbségek, amelyek a választásunkat szabályozzák:

  • Egy osztály Kotlinban annyi felületet valósíthat meg, amennyit csak akar, de csak egy absztrakt osztályból terjedhet ki
  • Az interfész tulajdonságai nem képesek fenntartani az állapotot, míg egy absztrakt osztályban

4.2. Mikor használjunk mit?

A kezelőfelület csak tervrajz az osztályok meghatározásához, opcionálisan rendelkezhetnek néhány alapértelmezett megvalósítással is. Másrészt az absztrakt osztály hiányos megvalósítás, amelyet a kibővítő osztályok töltenek be.

Jellemzően interfészeket kell használni a szerződés meghatározásához, amely kiváltja azokat a képességeket, amelyeket ígér. Egy megvalósító osztály felelős az ígéretek teljesítéséért. An Az elvont osztályt azonban fel kell használni a részleges jellemzők megosztására a kiterjesztő osztályokkal. Egy kiterjesztő osztály tovább tudja vinni a teljesítését.

5. Összehasonlítás a Java interfészekkel

A Java felület Java 8 változásaival, nagyon közel kerültek a Kotlin interfészekhez. Egyik korábbi cikkünk a Java 8-ban bevezetett új funkciókat foglalja magában, beleértve az interfész változtatásait is.

A Java és a Kotlin interfészek között többnyire szintaktikai különbségek vannak. Az egyik kiemelkedő különbség a „felülbírálás” kulcsszóval kapcsolatos. Kotlinban az interfészről örökölt elvont tulajdonságok vagy függvények megvalósításakor kötelező ezeket a „felülírja“. A Java-ban nincs ilyen kifejezett követelmény.

6. Következtetés

Ebben az oktatóanyagban megvitattuk a Kotlin interfészeket, hogyan definiálhatjuk és megvalósíthatjuk azokat. Ezután beszéltünk arról, hogy örököltük a több interfészt, és az általuk okozott konfliktusról. Megnéztük, hogyan kezeli Kotlin az ilyen konfliktusokat.

Végül megvitattuk az interfészeket Kotlin absztrakt osztályaihoz képest. Röviden beszéltünk arról is, hogy a Kotlin interfész hogyan viszonyul a Java felülethez.

Mint mindig, a példák kódja elérhető a GitHub oldalon.


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