IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

16. diel - Rozhranie (interface) v Kotlin

V predchádzajúcom cvičení, Riešené úlohy k 10.-15. lekciu OOP v Kotlin, sme si precvičili získané skúsenosti z predchádzajúcich lekcií.

V minulej lekcii, Riešené úlohy k 10.-15. lekciu OOP v Kotlin , sme si precvičili prácu s kolekciou List pri tvorbe elektronického diára. Dnes to bude opäť trochu teoretické, objavíme ďalšie topí objektovo orientovaného programovania, uvedieme si totiž rozhrania.

Rozhranie

Rozhraním objektu sa myslí to, ako je objekt viditeľný zvonku. Už vieme, že objekt obsahuje nejaké metódy, tie môžu byť privátne alebo verejné. Rozhranie objektu tvorí práve jeho verejné metódy, je to spôsob, akým s určitým typom objektu môžeme komunikovať. Už sme niekoľkokrát mohli vidieť aké verejné metódy naša trieda ponúka, napr. U nášho bojovníka do arény. Trieda Bojovnik mala nasledujúce verejné metódy:

  • utoc(souper: Bojovnik)
  • branSe(uder: Int)
  • nazivu(): Boolean
  • nastavZpravu(zprava: String)
  • vratPosledniZpravu(): String
  • grafickyZivot(): String

Pokiaľ si do nejakej premennej uložíme inštanciu bojovníka, môžeme na ňu volať metódy ako utoc() alebo branSe(). To stále nie je nič nové, že?

My si však rozhrania môžeme deklarovať zvlášť a to podobným spôsobom ako napríklad triedu. Toto rozhranie potom použijeme ako dátový typ.

Všetko si vyskúšame, ale na niečom jednoduchším, než je bojovník. Vytvorme si nový projekt a nazvime ho Rozhrani. Pridáme si nejakú jednoduchú triedu. Pretože by sa podľa môjho názoru mala teórie vysvetľovať na niečom odľahčujúcim, urobíme si Vtáka. Bude vedieť pípať, dýchať a jednoduchú recykláciu. Pridajme si triedu Ptak, bude vyzerať takto:

class Ptak {

    fun pipni() {
        println("♫ ♫ ♫")
    }

    fun dychej() {
        println("Dýchám...")
    }

    fun klovni() {
        println("Klov, klov!")
    }

}

Trieda je naozaj triviálne. Prejdime do Main.kt a vytvorme si inštanciu vtáka:

val ptak = Ptak()

Teraz napíšeme ptak. a necháme IntelliJ, aby nám zobrazil metódy na triede (možno tiež vyvolať stlačením Ctrl + Space):

Metódy na triede Ptak - Objektovo orientované programovanie v Kotlin

Vidíme, čo na vtákovi môžeme všetko volať. Sú tam samozrejme tie 3 metódy, čo sme v triede implementovali (plus ďalšie, ktoré majú objekty v základe).

Teraz vtákovi vytvoríme rozhranie. Využijeme na to kľúčového slova interface (anglicky rozhranie). Pomenovanie rozhranie v Kotlinu je pomerne veda (rovnako ako v Jave). My sa uspokojíme s názvom PtakInterface. Pravým tlačidlom klikneme na projekt a pridáme "New" -> "Kotlin File / Class". V dropdown menu vyberieme Interface.

Nový interface v Kotlinu - Objektovo orientované programovanie v Kotlin

K projektu sa nám pridá prázdny interface. Do neho pridáme hlavičky metód, ktoré má dané rozhranie obsahovať. Samotnú implementáciu (kód metód) uvedieme až v triede, ktorá bude toto rozhranie implementovať (viď ďalej).

Kotlín, rovnako ako Java od verzie 8, umožňuje uvádzať v rozhraní i tela metód, teda ich kód. To je proti tomu, čo si tu dnes budeme vysvetľovať, a táto funkcionalita vznikla z dôvodu podpory tzv. Trait. S tými sa pracuje inak ako s rozhraním a jazyky ako sú napr. PHP alebo Scala sú na túto funkcionalitu vlastné kľúčové slovo trait.

Do rozhrania PtakInterface teda pridáme hlavičky metód, schválne jednu vynecháme a pridáme iba Pípanie a Dýchanie:

interface PtakInterface {
    fun pipni()
    fun dychej()
}

Rozhranie obsahuje vždy len verejné metódy (inak by nemalo zmysel, udáva, ako s objektom zvonku pracovať).

Vráťme sa do Main.kt a zmeňme riadok s premennou ptak tak, aby už nebola typu Ptak, ale PtakInterface:

val ptak: PtakInterface = Ptak()

Kódom vyššie hovoríme, že v premennej typu PtakInterface očakávame objekt, ktorý poskytuje tie metódy, čo sú v rozhraní. Kotlín nám vynadá, pretože trieda Ptak zatiaľ rozhranie PtakInterface neimplementuje, aj keď potrebné metódy má, nevie, že rozhranie poskytuje. Presunieme sa do triedy Ptak a nastavíme jej, že implementuje interface PtakInterface. Implementovaným metódam dodáme kľúčové slovo override (rovnako ako u dedičnosti). Interface sa implementuje operátorom ::

class Ptak: PtakInterface {
    override fun pipni() {
        println("♫ ♫ ♫")
    }

    override fun dychej() {
        println("Dýchám...")
    }

    fun klovni() {
        println("Klov, klov!")
    }
}

Keď sa teraz vrátime do Main.kt, riadok s premennou typu PtakInterface je už v poriadku. Trieda Ptak korektne implementuje rozhranie PtakInterface a jej inštancie môže byť do premennej tohto typu uložená.

Skúsme teraz vymazať z triedy nejakú metódu, ktorú rozhranie udáva, napr. pipni(). IntelliJ nás upozorní, že implementácia nie je kompletný. Vráťme ju zas späť.

Opäť pridáme riadok ptak., IntelliJ nám ponúkne nasledujúce metódy:

Metódy vtáka s rozhraním PtakInterface - Objektovo orientované programovanie v Kotlin

Vidíme, že na inštanciu môžeme teraz volať iba metódy, ktoré poskytuje rozhranie. To preto, že premenná ptak je už typu PtakInterface, nie Ptak. Metóda klovni() úplne chýba.

K čomu je to dobré? Výhod a využitie je viac, na prvý sme už prišli. Pomocou rozhrania dokážeme zjednodušiť rozhranie nejakého zložitého objektu a vystaviť len tú časť, ktorá sa nám v tú dobu hodí.

Ešte dodám, že nemôžeme vytvoriť inštanciu z rozhrania, tento kód nebude fungovať:

// tento kód nebude fungovat
val ptak: PtakInterface = PtakInterface()

Viacnásobná dedičnosť

Kotlín (rovnako ako väčšina jazykov) nepodporuje viacnásobnú dedičnosť. Nemôžeme teda jednu triedu oddědit z niekoľkých iných tried. Je to hlavne z toho dôvodu, že môže vzniknúť problém kolízie názvov metód v rôznych triedach, z ktorých dedíme (Diamond problem). Viacnásobná dedičnosť sa často obchádza práve cez interface, pretože tých môžeme v triede implementovať koľko chceme. Umožňuje nám to s inštanciou potom pracovať určitým spôsobom a vôbec nás nezaujíma, akého typu objekt v skutočnosti je a čo všetko navyše obsahuje.

Pridajme si k projektu interface JesterInterface. Bude to interface jaštera. Ten bude vedieť tiež dýchať a ešte sa plaziť:

interface JesterInterface {
    fun plazSe()
    fun dychej()
}

Vyskúšajme si "viacnásobnú dedičnosť", presnejšie implementáciu viac rozhraní v jednej triede. Urobme si ptakoještěr. Pridajme k projektu triedu PtakoJester. Bude implementovať rozhranie PtakInterface a JesterInterface:

class PtakoJester: JesterInterface, PtakInterface {
}

Keď teraz klikneme na ikonu žiarovky, môžeme v kontextovom menu zvoliť možnosť "Implement members". IntelliJ nám automaticky do triedy vygeneruje potrebné metódy.

implementácia iNTERFACE - Objektovo orientované programovanie v Kotlin

Po implementácii oboch rozhranie vyzerá kód triedy takto:

class PtakoJester: JesterInterface, PtakInterface {
    override fun pipni() {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun plazSe() {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun dychej() {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
}

Metódy v Jester doimplementujeme:

override fun pipni() {
    println("♫ ♫♫ ♫ ♫ ♫♫")
}

override fun plazSe() {
    println("Plazím se...")
}

override fun dychej() {
    println("Dýchám...")
}

Presuňme sa do Main.kt a vytvorme si inštanciu ptakoještěr:

val ptakoJester = PtakoJester()

Uistime sa, že má metódy ako vtáka, tak jaštera:

Metódy vtáka a jaštera - Objektovo orientované programovanie v Kotlin

V budúcej lekcii, Pretypovania a hierarchie objektov v Kotlin , budeme pokračovať v podobnom duchu. Rozhranie ešte neopustíme a naučíme sa ďalšie pokročilé techniky objektovo orientovaného programovania.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 24x (23.18 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Kotlin

 

Predchádzajúci článok
Riešené úlohy k 10.-15. lekciu OOP v Kotlin
Všetky články v sekcii
Objektovo orientované programovanie v Kotlin
Preskočiť článok
(neodporúčame)
Pretypovania a hierarchie objektov v Kotlin
Článok pre vás napísal Samuel Kodytek
Avatar
Užívateľské hodnotenie:
1 hlasov
Autor se věnuje všem jazykům okolo JVM. Rád pomáhá lidem, kteří se zajímají o programování. Věří, že všichni mají šanci se naučit programovat, jen je potřeba prorazit tu bariéru, který se říká lenost.
Aktivity