C# týden Slevový týden - Březen
Využij náš slevový týden a získej až 30 % bodů navíc zdarma! Zároveň také probíhá C# týden se slevou na e-learning až 80 %
Hledáme fulltime programátora do ITnetwork týmu -100% homeoffice, 100% časově flexibilní #bezdeadlinu Mám zájem!

14. diel - Rozhranie (interface)

V predchádzajúcom cvičení Riešené úlohy k 12.-13. lekciu OOP v C # .NET sme si precvičili získané skúsenosti z predchádzajúcich lekcií.

V minulej lekcii, Riešené úlohy k 12.-13. lekciu OOP v C # .NET , sme si precvičili prácu s kolekciou List pri tvorbe elektronického diára. Dnes to v C # tutoriálu 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:

  • void Utoc(Bojovnik souper)
  • void BranSe(int uder)
  • bool Nazivu()
  • void NastavZpravu(string zprava)
  • string VratPosledniZpravu()
  • string GrafickyZivot()

    Pokiaľ si do nejakej úproměnné 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. 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, konzolovú aplikáciu 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, vytvoríme vtáka. Bude vedieť pípať, dýchať a jednoduchú recykláciu. Pridajme si triedu Ptak , bude vyzerať takto:

class Ptak
{

    public void Pipni()
    {
        Console.WriteLine("♫ ♫ ♫");
    }

    public void Dychej()
    {
        Console.WriteLine("Dýcham...");
    }

    public void Klovni()
    {
        Console.WriteLine("Kov, kov!");
    }

}

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

Ptak ptak = new Ptak();

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

metódy vtáka

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). Je dobrým zvykom, že rozhranie v C # začína vždy na písmeno I (ako Interface). Vytvorme teda interface IPtak . Pravým tlačidlom klikneme na projekt, a pridáme nový item -> Interface.

Nový interface vo Visual Studiu
Tento výukový obsah pomáhajú rozvíjať nasledujúce firmy, ktoré možno hľadajú práve teba!

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 IPtak teda pridáme hlavičky metód, schválne jednu vynecháme a pridáme iba pípanie a dýchanie:

interface IPtak
{
    void Pipni();
    void Dychej();
}

Modifikátor public neuvádzame, pretože rozhranie obsahuje vždy len 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 ptak tak, aby už nebola typu Ptak , ale IPtak :

IPtak ptak = new Ptak();

Kódom vyššie hovoríme, že v premennej typu IPtak očakávame objekt, ktorý obsahuje tie metódy, čo sú v rozhraní. Visual Studio nám vynadá, pretože trieda Ptak zatiaľ rozhranie IPtak neobsahuje, aj keď potrebné metódy má, nevie, že rozhranie poskytuje. Presunieme sa do triedy Ptak a nastavíme jej, že implementuje interface IPtak . Robí sa to rovnako, ako keď trieda od inej dedí:

class Ptak: IPtak
{
    // . . .

Keď sa teraz vrátime do Program.cs , riadok s premennou typu IPtak je už v poriadku. Trieda Ptak korektne implementuje rozhranie IPtak 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() . Visual Studio nás upozorní, že implementácia nie je kompletný. Vráťme ju zas späť.

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

Metódy vtáka s rozhraním IPtak

Vidíme, že na inštanciu môžeme teraz volať iba metódy, ktoré poskytuje rozhranie. To preto, že premenná ptak je už typu IPtak , 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 fungovať
IPtak ptak = new IPtak();

Viacnásobná dedičnosť

C # (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 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 IJester . Bude to interface jaštera. Ten bude vedieť tiež dýchať a ešte sa plaziť:

interface IJester
{
    void PlazSe();
    void 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.cs . Bude implementovať rozhranie IPtak a IJester :

class PtakoJester: IJester, IPtak
{
}

Keď teraz klikneme v tomto kóde pravým tlačidlom na jednotlivé interface (teda na IJester a IPtak ), môžeme v kontextovom menu zvoliť možnosť Implement Interface. Visual Studio nám potom do triedy automaticky vygeneruje potrebné metódy.

Automatická implementácia

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

class PtakoJester: IJester, IPtak
{
    public void PlazSe()
    {
        throw new NotImplementedException();
    }

    public void Dychej()
    {
        throw new NotImplementedException();
    }

    public void Pipni()
    {
        throw new NotImplementedException();
    }
}

Metódy doimplementujeme:

public void PlazSe()
{
    Console.WriteLine("Plazím sa...");
}

public void Dychej()
{
    Console.WriteLine("Dýcham...");
}

public void Pipni()
{
    Console.WriteLine("♫ ♫♫ ♫ ♫ ♫♫");
}

A presuňme sa do Program.cs a vytvorme si inštanciu ptakoještěr:

PtakoJester ptakojester = new PtakoJester();

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

Metódy vtáka a jaštera

V budúcej lekcii, Pretypovania a hierarchie 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.


 

Stiahnuť

Stiahnuté 832x (23.49 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C#

 

 

Článok pre vás napísal David Čápka
Avatar
Ako sa ti páči článok?
Ešte nikto nehodnotil, buď prvý!
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor sa informačné technológie naučil na Unicorn College - prestížnej súkromnej vysokej škole IT a ekonómie.
Predchádzajúci článok
Riešené úlohy k 12.-13. lekciu OOP v C # .NET
Všetky články v sekcii
Objektovo orientované programovanie v C #
Miniatúra
Nasledujúci článok
Pretypovania a hierarchie objektov
Aktivity (1)

 

 

Komentáre

Avatar
Ondřej Čech:20.11.2017 17:06

Mně ten right click nezobrazuje takové menu. Asi jinačí verze Visualka. Musím tam přes tu žárovečku, která mi nabídne jak opravit chybu a doimplementuje to. Nebo jsem jen vocas a něco jsem někde přehlédl?

 
Odpovedať
20.11.2017 17:06
Avatar
Odpovedá na Ondřej Čech
Markéta Zdanovcová:13.12.2017 15:25

Taky to mam tak :)

 
Odpovedať
13.12.2017 15:25
Avatar
Milan
Člen
Avatar
Milan:4.7.2018 20:29

Ahoj, můžu v třídě, ve které je implementovaný interface, respektive metody z interface je udělat nějakým způsobem privátní? Chápu, že interface musí být public, ale proč nemůžu udělat private metodu v třídě? Díky za odpověď.

 
Odpovedať
4.7.2018 20:29
Avatar
Odpovedá na Milan
Michal Šmahel:4.7.2018 20:40

Ahoj, asi jsi správně nepochopil význam rozhraní. Rozhraní se používají pro to, že definují, jak se třída bude chovat navenek. Z toho vyplývá, že definují povinné veřejné metody, skrz ně následně můžeme přistupovat ke každé třídě implementující dané rozhraní. Pro tvé potřeby se raději podívej po abstraktních třídách.

Odpovedať
4.7.2018 20:40
Nejdůležitější je motivace, ovšem musí být doprovázena činy.
Avatar
Milan
Člen
Avatar
Odpovedá na Michal Šmahel
Milan:4.7.2018 20:45

Díky za odpověď. Já to spíše bral tak, že si udělám seznam metod, které budu potřebovat a implementací interface na ně nezapomenu. Ale v tom případě tomu rozumím, děkuji.

 
Odpovedať
4.7.2018 20:45
Tento výukový obsah pomáhajú rozvíjať nasledujúce firmy, ktoré možno hľadajú práve teba!
Avatar
Odpovedá na Milan
Michal Šmahel:4.7.2018 20:56

Potom ti pomůže abstraktní třída.

Odpovedať
4.7.2018 20:56
Nejdůležitější je motivace, ovšem musí být doprovázena činy.
Avatar
Michael K.
Člen
Avatar
Michael K.:2.5.2019 10:55

Jedna věc mi není ohledně Interface jasná.

Jaký je rozdíl mezi
IPtak ptak = new Ptak(); a Ptak ptak = new Ptak();

přeci pokud implementuji rozhraní IPtak ve tříde Ptak, tak tam implementovány metody budou.

Nebo jo to ochrana před tím, kdyby třída Ptak rozhraní IPtak neimplementovalo ?

Polopaticky řečeno - tím, že napíšu IPtak ptak = new Ptak(); kompilátoru řeknu, ověř mi, zda třída Ptak implementuje rohzraní IPtak ? Chápu to dobře ?

Jak by to bylo v případě, že bych chtěl zajistit, aby třída Ptak implementovala více rozhraní ? Při vytváření instance si musím vybrat pouze jednu ?

Děkuji

 
Odpovedať
2.5.2019 10:55
Avatar
David Jančík
Tým ITnetwork
Avatar
Odpovedá na Michael K.
David Jančík:2.5.2019 11:30

Tvůj dotaz je v článku zodpovězen:

K čemu je to dobré? Výhod a využití je více, na první jsme již přišli. Pomocí rozhraní dokážeme zjednodušit rozhraní nějakého složitého objektu a vystavit jen tu část, která se nám v tu dobu hodí.

Odpovedať
2.5.2019 11:30
Zapomeň, že je to nemožné a udělej to ;)
Avatar
Michael K.
Člen
Avatar
Michael K.:2.5.2019 11:36

Takže pokud by třída Ptak implementovala další rozhraní (například.:

interface IPridejDoDatabaze { public void PridaniDoDatabaze();}

a já vytvořím instanci IPtak ptak = new Ptak(); tak metodu PirdaniDoDatabaze() neuvidím/nemohu ji použít ? Chápu to dobře?

Editované 2.5.2019 11:37
 
Odpovedať
2.5.2019 11:36
Avatar
vosa53
Člen
Avatar
Odpovedá na Michael K.
vosa53:2.5.2019 14:12

Ano, pokud ji nepřetypuješ.

IPtak ptak1 = new Ptak();
ptak1.PridaniDoDatabaze(); // Compile time error

Ptak ptak2 = (Ptak)ptak1;
ptak2.PridaniDoDatabaze(); // Lze

IPridejDoDatabaze ptak3 = (IPridejDoDatabaze)ptak1;
ptak3.PridaniDoDatabaze(); // Lze
 
Odpovedať
2.5.2019 14:12
Robíme čo je v našich silách, aby bola tunajšia diskusia čo najkvalitnejšia. Preto do nej tiež môžu prispievať len registrovaní členovia. Pre zapojenie sa do diskusie sa zaloguj. Ak ešte nemáš účet, zaregistruj sa, je to zadarmo.

Zatiaľ nikto nevložil komentár - buď prvý!