Letní akce! Lákají tě IT školení C#, Javy a PHP v Brně? Přihlas se a napiš nám do zpráv kód "BRNO 500" pro slevu 500 Kč na libovolný brněnský kurz. Lze kombinovat se slevami uvedenými u školení i použít pro více kurzů. Akce končí 28.7.

Lekce 14 - Rozhraní (interface)

C# .NET Objektově orientované programování Rozhraní (interface) American English version English version

ONEbit hosting Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Diář s databází v C#, jsme si procvičili práci s kolekcí List při tvorbě elektronického diáře. Dnes to v C# tutoriálu bude opět trochu teoretické, objevíme další taje objektově orientovaného programování, uvedeme si totiž rozhraní.

Rozhraní

Rozhraním objektu se myslí to, jak je objekt viditelný zvenku. Již víme, že objekt obsahuje nějaké metody, ty mohou být privátní nebo veřejné. Rozhraní objektu tvoří právě jeho veřejné metody, je to způsob, jakým s určitým typem objektu můžeme komunikovat. Již jsme několikrát mohli vidět jaké veřejné metody naše třída nabízí, např. u našeho bojovníka do arény. Třída Bojovnik měla následující veřejné metody:

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

Pokud si do nějaké úproměnné uložíme instanci bojovníka, můžeme na ni volat metody jako Utoc() nebo BranSe(). To pořád není nic nového, že?

My si však rozhraní můžeme deklarovat zvlášť a to podobným způsobem jako např. třídu. Toto rozhraní poté použijeme jako datový typ.

Vše si vyzkoušíme, ale na něčem jednodušším, než je bojovník. Vytvořme si nový projekt, konzolovou aplikaci a nazvěme ho Rozhrani. Přidáme si nějakou jednoduchou třídu. Protože by se dle mého názoru měla teorie vysvětlovat na něčem odlehčujícím, vytvoříme ptáka. Bude umět pípat, dýchat a klovat. Přidejme si třídu Ptak, bude vypadat takto:

class Ptak
{

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

        public void Dychej()
        {
                Console.WriteLine("Dýchám...");
        }

        public void Klovni()
        {
                Console.WriteLine("Klov, klov!");
        }

}

Třída je opravdu triviální. Přejděme do Program.cs a vytvořme si instanci ptáka:

Ptak ptak = new Ptak();

Nyní napíšeme ptak. a necháme Visual Studio, aby nám zobrazilo metody na třídě (lze také vyvolat stiskem ctrl + space):

Metody ptáka

Vidíme, co na ptákovi můžeme vše volat. Jsou tam samozřejmě ty 3 metody, co jsme ve třídě implementovali (plus další, které mají objekty v základu).

Nyní ptákovi vytvoříme rozhraní. Využijeme k tomu klíčového slova interface (anglicky rozhraní). Je dobrým zvykem, že rozhraní v C# začíná vždy na písmeno I (jako Interface). Vytvořme tedy interface IPtak. Pravým tlačítkem klikneme na projekt, a přidáme nový item -> Interface.

Nový interface ve Visual Studiu

K projektu se nám přidá prázdný interface. Do něj přidáme hlavičky metod, které má dané rozhraní obsahovat. Samotnou implementaci (kód metod) uvedeme až ve třídě, která bude toto rozhraní implementovat (viz dále).

Do rozhraní IPtak tedy přidáme hlavičky metod, schválně jednu vynecháme a přidáme pouze pípání a dýchání:

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

Modifikátor public neuvádíme, protože rozhraní obsahuje vždy pouze veřejné metody (jinak by nemělo smysl, udává, jak s objektem zvenku pracovat).

Vraťme se do Program.cs a změňme řádek s proměnnou ptak tak, aby již nebyla typu Ptak, ale IPtak:

IPtak ptak = new Ptak();

Kódem výše říkáme, že v proměnné typu IPtak očekáváme objekt, který obsahuje ty metody, co jsou v rozhraní. Visual Studio nám vyhubuje, protože třída Ptak zatím rozhraní IPtak neobsahuje, i když potřebné metody má, neví, že rozhraní poskytuje. Přesuneme se do třídy Ptak a nastavíme jí, že implementuje interface IPtak. Dělá se to stejně, jako když třída od jiné dědí:

class Ptak: IPtak
{
        // . . .

Když se nyní vrátíme do Program.cs, řádek s proměnnou typu IPtak je již v pořádku. Třída Ptak korektně implementuje rozhraní IPtak a její instance může být do proměnné tohoto typu uložena.

Zkusme nyní vymazat ze třídy nějakou metodu, kterou rozhraní udává, např. Pipni(). Visual Studio nás upozorní, že implementace není kompletní. Vraťme ji zas zpět.

Opět přidáme řádek ptak., Visual Studio nám nabídne následující metody:

Metody ptáka s rozhraním IPtak

Vidíme, že na instanci můžeme nyní volat pouze metody, které poskytuje rozhraní. To proto, že proměnná ptak je již typu IPtak, nikoli Ptak. Metoda Klovni() úplně chybí.

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í.

Ještě dodám, že nemůžeme vytvořit instanci z rozhraní, tento kód nebude fungovat:

// tento kód nebude fungovat
IPtak ptak = new IPtak();

Vícenásobná dědičnost

C# (stejně jako většina programovacích jazyků) nepodporuje vícenásobnou dědičnost. Nemůžeme tedy jednu třídu oddědit z několika jiných tříd. Je to hlavně z toho důvodu, že může vyvstat problém kolize názvů metod v různých třídách, ze kterých dědíme. Vícenásobná dědičnost se často obchází právě přes interface, protože těch můžeme ve třídě implementovat kolik chceme. Umožňuje nám to s instancí poté pracovat určitým způsobem a vůbec nás nezajímá, jakého typu objekt ve skutečnosti je a co všechno navíc obsahuje.

Přidejme si k projektu interface IJester. Bude to interface ještěra. Ten bude umět také dýchat a ještě se plazit:

interface IJester
{
        void PlazSe();
        void Dychej();
}

Vyzkoušejme si "vícenásobnou dědičnost", přesněji implementaci více rozhraní v jedné třídě. Udělejme si ptakoještěra. Přidejme k projektu třídu PtakoJester.cs. Bude implementovat rozhraní IPtak a IJester:

class PtakoJester: IJester, IPtak
{
}

Když nyní klikneme v tomto kódu pravým tlačítkem na jednotlivé interface (tedy na IJester a IPtak), můžeme v kontextovém menu zvolit možnost Implement Interface. Visual Studio nám poté do třídy automaticky vygeneruje potřebné metody.

Automatická implementace

Po implementaci obou rozhraní vypadá kód třídy takto:

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

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

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

Metody doimplementujeme:

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

public void Dychej()
{
        Console.WriteLine("Dýchám...");
}

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

A přesuňme se do Program.cs a vytvořme si instanci ptakoještěra:

PtakoJester ptakojester = new PtakoJester();

Ujistěme se, že má metody jak ptáka, tak ještěra:

Metody ptáka a ještěra

V příští lekci, Přetypování a hierarchie objektů, budeme pokračovat v podobném duchu. Rozhraní ještě neopustíme a naučíme se další pokročilé techniky objektově orientovaného programování.


 

Stáhnout

Staženo 750x (23.49 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

 

Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
21 hlasů
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 sítě se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Miniatura
Předchozí článek
Diář s databází v C#
Miniatura
Následující článek
Přetypování a hierarchie objektů
Aktivity (7)

 

 

Komentáře
Zobrazit starší komentáře (51)

Avatar
Jan Voráček:2.11.2017 14:07

Pro nás pomalejší ještě jednodušeji. Znamená to tedy, že Implement Interface v podstatě jen automaticky vytvoří hlavičku metody a tu metodu si pak už musím vytvořit sám?
Pokud ano, tak by možná stálo za to lehce poupravit ten tutoriál. Dlouho jsem se marně snažil najít nějaké menu podobné Imnplement Interface, které by to doimplementování zmíněné v nadpisu obrázku udělalo za mne.

 
Odpovědět 2.11.2017 14:07
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Jan Voráček
David Čápka:2.11.2017 15:02

Dlouho jsem se marně snažil najít nějaké menu podobné Imnplement Interface, které by to doimplementování zmíněné v nadpisu obrázku udělalo za mne.

Vždyť tam máš ukázané jak se do toho menu dostaneš.

Odpovědět 2.11.2017 15:02
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Petr Nymsa
Redaktor
Avatar
Odpovídá na Jan Voráček
Petr Nymsa:2.11.2017 18:27

Samozřejmě, že VS pomůže jen vygenerovat všechny hlavičky metod. Těla si musíš implementovat sám. Není v silách žádného IDE vědět, jaký kód daná metoda má provádět.

Odpovědět  +2 2.11.2017 18:27
Pokrok nezastavíš, neusni a jdi s ním vpřed
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Petr Nymsa
David Čápka:2.11.2017 18:42

Jo on to myslel, že se mu to samo naprogramuje, to mě ani nenapadlo :D

Odpovědět  +2 2.11.2017 18:42
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
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?

 
Odpovědět 20.11.2017 17:06
Avatar
 
Odpovědět 13.12.2017 15:25
Avatar
Milan
Člen
Avatar
Milan:4. července 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ěď.

 
Odpovědět 4. července 20:29
Avatar
Odpovídá na Milan
Michal Šmahel:4. července 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.

Odpovědět 4. července 20:40
Nejdůležitější je motivace, ovšem musí být doprovázena činy.
Avatar
Milan
Člen
Avatar
Odpovídá na Michal Šmahel
Milan:4. července 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.

 
Odpovědět 4. července 20:45
Avatar
Odpovídá na Milan
Michal Šmahel:4. července 20:56

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

Odpovědět 4. července 20:56
Nejdůležitější je motivace, ovšem musí být doprovázena činy.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 61. Zobrazit vše