11. diel - Protokoly (rozhranie) vo Swift
V minulej lekcii, Vlastnosti vo Swift , sme si precvičili prácu s vlastnosťami. Dnes to vo Swift tutoriálu bude opäť trochu teoretické, objavíme ďalšie topí objektovo orientovaného programovania, uvedieme si totiž tzv. Rozhranie, ktoré Swift implementuje ako protokoly.
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:
func utoc(souper: Bojovnik)
func branSe(uder: Int)
func nazivu() -> Bool
func nastavZpravu(zprava: String)
func vratPosledniZpravu() -> String
func 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. Triedu. Hovoríme, že sme vytvorili protokol. A tento protokol definujúci 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, konzolovú aplikáciu a nazvime ho
Protokoly
. 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,
vytvoríme vtáka. Bude vedieť pípať, dýchať a jednoduchú recykláciu.
Pridajme si triedu Ptak
, bude vyzerať takto:
class Ptak { func pipni() { print("♫ ♫ ♫") } func dychej() { print("Dýchám...") } func klovni() { print("Klov, klov!") } }
Trieda je naozaj triviálne. Prejdime do main.swift
a vytvorme
si inštanciu vtáka:
let ptak = Ptak()
Teraz napíšeme ptak.
a necháme Xcode, aby nám zobrazilo
metódy na triede (možno tiež vyvolať stlačením Ctrl +
Space):
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 protokol. Využijeme na to kľúčového slova
protocol
. Názvy protokolov často končí
anglickú koncovkou -able
, takže môžeme mať
Printable
, Convertible
, Renderable
pod. Z
protokolu je vlastne vidieť, akú funkcionalitu ponúka. Napr.
Renderable
môže znamenať, že pôjde vyrenderovať, čiže
zobraziť ako súčasť UI.
Pre zjednodušenie náš protokol pomenujeme PtakProtokol
a
pokojne ho môžeme pre zjednodušenie umiestniť do súboru
Ptak.swift
nad triedu Ptak
. Tiež si definujeme
požadované metódy:
protocol PtakProtokol { func pipni() func dychej() }
Modifikátor public
neuvádzame, pretože protokol obsahuje
vždy len verejné metódy (inak by nemal zmysel, udáva, ako s objektom zvonku
pracovať).
Vráťme sa do main.swift
a zmeňme riadok s premennou
ptak
tak, aby už nebola typu Ptak
, ale
PtakProtokol
:
let ptak : PtakProtokol = Ptak()
Kódom vyššie hovoríme, že v premennej typu PtakProtokol
očakávame objekt, ktorý obsahuje tie metódy, čo sú v protokole. Xcode nám
vynadá, pretože trieda Ptak
zatiaľ protokol
PtakProtokol
neobsahuje, aj keď potrebné metódy má, nevie, že
protokol poskytuje. Presunieme sa do triedy Ptak
a nastavíme jej,
že implementuje protokol PtakProtokol
. Robí sa to rovnako, ako
keď trieda od inej dedí:
class Ptak: PtakProtokol { // . . .
Keď sa teraz vrátime do main.swift
, riadok s premennou typu
PtakProtokol
je už v poriadku. Trieda Ptak
korektne
implementuje protokol PtakProtokol
a jej inštancie môže byť do
premennej tohto typu uložená.
Skúsme teraz vymazať z triedy nejakú metódu, ktorú protokol udáva,
napr. pipni()
. Xcode nás upozorní, že implementácia nie je
kompletný. Vráťme ju zas späť.
Opäť pridáme riadok ptak.
, Xcode nám ponúkne nasledujúce
metódy:
Vidíme, že na inštanciu môžeme teraz volať iba metódy, ktoré
poskytuje protokol. To preto, že premenná ptak
je už typu
PtakProtokol
, 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 protokolov dokážeme zjednodušiť protokol 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 protokolu, tento kód nebude fungovať:
// tento kód nebude fungovat let ptak : PtakProtokol = PtakProtokol()
Viacnásobná dedičnosť
Swift (rovnako ako väčšina programovacích 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. Viacnásobná
dedičnosť sa často obchádza práve cez protocol
, 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 protocol
JesterProtokol
. Bude to protokol jaštera. Ten
bude vedieť tiež dýchať a ešte sa plaziť. Pre zjednodušenie môžete
protokol vytvoriť v aktuálnom súbore Ptak.swift
alebo si
založiť nový Swift súbor:
protocol JesterProtokol { func plazSe() func dychej() }
Vyskúšajme si "viacnásobnú dedičnosť", presnejšie implementáciu
viacerých protokolov v jednej triede. Urobme si ptakoještěr. Pridajme k
projektu triedu PtakoJester.swift
. Bude implementovať protokoly
PtakProtokol
a JesterProtokol
:
class PtakoJester: PtakProtokol, JesterProtokol {
}
Keď teraz klikneme v tomto kóde pravým tlačidlom na
PtakoJester
v definícii triedy, môžeme v kontextovom menu
zvoliť Refactor -> Add Missing Protocol Requierements a Xcode nám
vygeneruje potrebné metódy, takže ich stačí implementovať.
Po implementácii oboch protokolov vyzerá kód triedy takto,
<#code#>
je v Xcode špeciálny placeholder pre kód:
class PtakoJester: PtakProtokol, JesterProtokol { func pipni() { <#code#> } func dychej() { <#code#> } func plazSe() { <#code#> } func dychej() { <#code#> } }
Xcode z nejakého dôvodu vygenerovalo metódu dychej()
dvakrát, ak sa vám to tiež stane, stačí jednu z nich zmazať.
Metódy doimplementujeme:
func pipni() { print("♫ ♫♫ ♫ ♫ ♫♫") } func dychej() { print("Dýchám ...") } func plazSe() { print("Plazím se...") }
A presuňme sa do main.swift
a vytvorme si inštanciu
ptakoještěr:
let ptakojester = PtakoJester()
Uistite sa, že má metódy z vtáka i jaštera. Mne sa bohužiaľ zbláznilo
Xcode a v nápovede ukazovalo 3x metódu dychej()
. Krátky výlet
na Google ukázal, že to nie je ojedinelý problém ... Bohužiaľ, na druhú
stranu nejde o nič kritického.
V budúcej lekcii, Pretypovania a hierarchie objektov vo Swift , budeme pokračovať v podobnom duchu. Protokoly ešte neopustíme a naučíme sa ďalšie pokročilé techniky objektovo orientovaného programovania.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkamiStiahnuté 11x (18.42 kB)