15. diel - Rozhranie (interface)
V minulej lekcii, Diár s databázou v C#, sme si precvičili prácu s kolekciou
List
pri tvorbe elektronického diára.
Dnes to v C# tutoriále bude opäť trochu teoretické, objavíme ďalšie tajomstvá objektovo orientovaného programovania, uvedieme si totiž rozhranie.
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 Warrior
mala nasledujúce verejné metódy:
void Attack(Warrior enemy)
void Defend(int hit)
bool Alive()
void SetMessage(string message)
string GetLastMessage()
string HealthBar()
Pokiaľ si do nejakej úpromennej uložíme inštanciu bojovníka, môžeme
na ňu volať metódy ako Attack()
alebo Defend()
. To
stále nie je nič nové, že?
My si však rozhranie môžeme deklarovať zvlášť, a to podobným spôsobom ako napr. triedu. Toto rozhranie potom použijeme ako dátový typ.
Všetko si vyskúšame, ale na niečom jednoduchšom, než je bojovník.
Vytvorme si nový projekt, konzolovú aplikáciu a nazvime ho
InterfaceSample
. Pridáme si nejakú jednoduchú triedu. Pretože
by sa podľa môjho názoru mala teória vysvetľovať na niečom
odľahčujúcom, vytvoríme vtáka. Bude vedieť cvrtilikať, dýchať a
klovať. Pridajme si triedu Bird
, bude vyzerať takto:
class Bird { public void Chirp() { Console.WriteLine("♫ ♫ ♫"); } public void Breathe() { Console.WriteLine("Breathing..."); } public void Peck() { Console.WriteLine("Peck, peck!"); } }
Trieda je naozaj triviálna. Prejdime do Program.cs
a vytvorme
si inštanciu vtáka:
Bird bird = new Bird();
Teraz napíšeme bird.
a necháme Visual Studio, 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 tri 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é slovo
interface
(anglicky rozhranie). Je dobrým zvykom, že rozhranie v
C# začína vždy na písmeno I
(ako Interface). Vytvorme teda
interface IBird
. Pravým tlačidlom klikneme na projekt a zvolíme
Add > New Item -> Interface:
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).
Do rozhrania IBird
teda pridáme hlavičky metód, schválne
jednu vynecháme a pridáme iba cvrtlikanie a dýchanie:
interface IBird { void Chirp(); void Breathe(); }
Modifikátor public
neuvádzame, pretože rozhranie obsahuje
vždy iba verejné metódy (inak by nemalo zmysel, udáva, ako s objektom zvonku
pracovať).
Vráťme sa do Program.cs
a zmeňme riadok s premennou
bird
tak, aby už nebola typu Bird
, ale
IBird
:
IBird bird = new Bird();
Kódom vyššie hovoríme, že v premennej typu IBird
očakávame objekt, ktorý obsahuje tie metódy, čo sú v rozhraní. Visual
Studio nám vyhubuje, pretože trieda Bird
zatiaľ rozhranie
IBird
neobsahuje, aj keď potrebné metódy má, nevie, že
rozhranie poskytuje. Presunieme sa do triedy Bird
a nastavíme jej,
že implementuje interface IBird
. Robí sa to rovnako, ako keď
trieda od inej dedí:
class Bird: IBird { // ...
Keď sa teraz vrátime do Program.cs
, riadok s premennou typu
IBird
je už v poriadku. Trieda Bird
korektne
implementuje rozhranie IBird
a jej inštancia môže byť do
premennej tohto typu uložená.
Skúsme teraz vymazať z triedy nejakú metódu, ktorú rozhranie udáva,
napr. Chirp()
. Visual Studio nás upozorní, že implementácia nie
je kompletná. Vráťme ju zas späť.
Opäť pridáme riadok bird.
, Visual Studio nám ponúkne
nasledujúce metódy:
Vidíme, že na inštanciu môžeme teraz volať iba metódy, ktoré
poskytuje rozhranie. To preto, že premenná bird
je už typu
IBird
, nie Bird
. Metóda Peck()
úplne
chýba.
Na čo 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 tom čase hodí.
Ešte dodám, že nemôžeme vytvoriť inštanciu z rozhrania, tento kód nebude fungovať:
// this code won't work IBird bird = new IBird();
Viacnásobná dedičnosť
C# (rovnako ako väčšina programovacích jazykov) nepodporuje viacnásobnú
dedičnosť. Nemôžeme teda jednu triedu oddediť z niekoľkých iných tried.
Je to hlavne z toho dôvodu, že môže vyvstať 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 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 InterfaceSample
rozhranie
ILizard
. Bude to interface jaštera. Ten bude vedieť tiež
dýchať a ešte sa plaziť:
interface ILizard { void Crawl(); void Breathe(); }
Vyskúšajme si "viacnásobnú dedičnosť", presnejšie implementáciu
viacerých rozhraní v jednej triede. Urobme si vtákoještera. Pridajme k
projektu triedu Pterodactyl.cs
. Bude implementovať rozhranie
IBird
a ILizard
:
class Pterodactyl: ILizard, IBird
{
}
Keď teraz klikneme v tomto kóde pravým tlačidlom na jednotlivé interface
(teda na ILizard
a IBird
), môžeme v kontextovom menu
zvoliť možnosť Implement interface a Visual Studio nám potom do
triedy automaticky vygeneruje potrebné metódy:
Po implementácii oboch rozhraní vyzerá kód triedy takto:
class Pterodactyl: ILizard, IBird { public void Crawl() { throw new NotImplementedException(); } public void Breathe() { throw new NotImplementedException(); } public void Chirp() { throw new NotImplementedException(); } }
Metódy doimplementujeme:
public void Crawl() { Console.WriteLine("I'm crawling..."); } public void Breathe() { Console.WriteLine("I'm breathing..."); } public void Chirp() { Console.WriteLine("♫ ♫♫ ♫ ♫ ♫♫"); }
A presuňme sa do Program.cs
a vytvorme si inštanciu
vtákoještera:
Pterodactyl pterodactyl = new Pterodactyl();
Uistime sa, že má metódy ako vtáka, tak aj jaštera:
V budúcej lekcii, Pretypovanie a hierarchia objektov, 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é 4x (56.5 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C#