PHP týden Předvánoční slevová akce
Pouze tento týden sleva až 80 % na PHP e-learning!
Využij předvánočních slev a získej od nás 20 % bodů zdarma! Více zde

Lekce 14 - Rozhraní (interface)

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
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

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 819x (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?
27 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.
Předchozí článek
Diář s databází v C#
Všechny články v sekci
Objektově orientované programování v C#
Miniatura
Následující článek
Přetypování a hierarchie objektů
Aktivity (10)

 

 

Komentáře

Avatar
Lako
Neregistrovaný
Avatar
Lako:7.4.2013 13:04

Děkuji za pěkný článek. Asi zatím nejlepší vysvětlení rozhraní, které jsem dostal.
Všude slýchávám, že se má programovat prosti rozhraní... Mohl bys tuto větu objasnit - nějak srozumitelně, ale na konkrétním příkladu?

 
Odpovědět
7.4.2013 13:04
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Lako
David Čápka:7.4.2013 13:56

Prosti rozhraní?

Odpovědět
7.4.2013 13:56
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
Homo
Člen
Avatar
Odpovídá na David Čápka
Homo:7.4.2013 13:59

Nejspis myslel proti rozhrani.
Ze ma treba pole interfacu ITvar a v nem ma instance trid ktere toto rozhrani obsahuji.

Odpovědět
7.4.2013 13:59
1010011 1000101 1011000
Avatar
Drahomír Hanák
Tým ITnetwork
Avatar
Odpovídá na Lako
Drahomír Hanák:7.4.2013 14:02

Jednak rozhraní (ve smyslu public metod a vlastností) je něco, přes co komunikuješ s objektem. Pak je tu rozhraní jako interface, což je to klíčové slovo, ve kterém definuješ, jaké všechny public metody a vlastnosti má mít třída implementující tvoje rozhraní (interface). Programováním proti rozhraní oddělíš výčet public metod a vlastností od jeho konkrétní implementace (tzn. toho, co ty metody dělají) a to můžeš v případě potřeby změnit. Pokud bys ale změnil public metody a vlastnosti (jejich názvy, parametry atp.), bývá to většinou problematické.

Příklad:
Když máš třeba přihlášení uživatele a chceš, aby se uživatel mohl přihlásit z víc zdrojů (facebook, twitter, vlastní účet) Pokaždé to samotné ověřování bude jiné, ale pokaždé budeš chtít jedinou metodu, která ověří uživatele ze zadaných dat. Uděláš si tedy interface s metodami třeba overUzivatele() a je ti jedno, jak budeš uživatele ověřovat. O to se postarají třídy, které tvé rozhraní implementují. Pak můžeš předávat dalším třídám typ IAuthenticator a je pořád jedno, přes co se připojuješ. Kódu, který tu třídu používá, stačí vědět, že může zavolat metodu overUzivatele() Tím pádem můžeš i přidat novou možnost přihlášení (dejme tomu přes google). Když třída, poskytující přihlášení přes google implementuje tvoje rozhraní, nikdo nic nepozná a najednou ti funguje přihlašování pomocí googlu.

Hlavní myšlenka toho je, že funkčnost se může měnit, rozšiřovat, zlepšovat, ale to, jak k ní přistupuješ (přes nějaké public rozhraní) se moc často nemění, protože je to velmi problematické. To ti umožní právě programování proti rozhraní, protože předáváš jen výčet metod, se kterými všichni mohou pracovat, ale je ti jedno, jak to vnitřně funguje.

 
Odpovědět
7.4.2013 14:02
Avatar
Lako
Neregistrovaný
Avatar
Odpovídá na Drahomír Hanák
Lako:7.4.2013 14:30

@drahoš:
ó děkuji.
Pěkný příklad s tím přihlášení.

@sdraco: samozřejmě jsem myslel proti, upsal jsem se.

 
Odpovědět
7.4.2013 14:30
Avatar
Petr Nymsa
Redaktor
Avatar
Odpovídá na David Čápka
Petr Nymsa:19.5.2013 22:07

Jak to přesně funguje v rozhraní s vlastnostmi? Potřeboval bych si udělat rozhraní, kde bude něco jako

bool Solid { get;}

tedy pouze lze zvenčí číst. Ve třídě, která implementuje rozhraní musím tedy připsat k Solid ještě private set,abych to mohl přes konstruktor nastavit. Určuju tím jestli můžu do objektu narazit nebo ne. Je takto vše správně ?

Odpovědět
19.5.2013 22:07
Pokrok nezastavíš, neusni a jdi s ním vpřed
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Petr Nymsa
David Čápka:20.5.2013 9:34

Jo, vlastnosti se překládají interně na metody, proto mohou být v interface. Větší smysl mi ale dává:

bool Solid { get; private set; }
Odpovědět
20.5.2013 9:34
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 David Čápka
Petr Nymsa:20.5.2013 10:35

A to nastavit v interface ? Kompilátor mi tam pak hlásí chybu

Odpovědět
20.5.2013 10:35
Pokrok nezastavíš, neusni a jdi s ním vpřed
Avatar
Kit
Redaktor
Avatar
Odpovídá na Petr Nymsa
Kit:20.5.2013 10:42

A jakou chybu hlásí? Prozradíš nám to nebo to máme věštit z křišťálové koule?

Samozřejmě to musíš nastavit nejen v interface, ale i v implementaci.

Odpovědět
20.5.2013 10:42
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Petr Nymsa
David Čápka:20.5.2013 10:55

Nedošlo mi, že ten privátní setter to nepovolí. Takže to má být jak říkáš.

Odpovědět
20.5.2013 10:55
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 Kit
Petr Nymsa:20.5.2013 11:06

Jo omlouvám se :D .. accessibility modifiers may not be used on accessors in an interface

David Čápka jo takhle to funguje

Díky

Odpovědět
20.5.2013 11:06
Pokrok nezastavíš, neusni a jdi s ním vpřed
Avatar
Kit
Redaktor
Avatar
Odpovídá na David Čápka
Kit:20.5.2013 11:09

Také mi došlo, že privátní setter je de facto zbytečný.

Odpovědět
20.5.2013 11:09
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Kit
Redaktor
Avatar
Odpovídá na Petr Nymsa
Kit:20.5.2013 11:12

Aha, takže v interface nejsou povoleny modifikátory přístupu. Teď mi vrtá hlavou, zda je možné je použít v implementaci. Asi ne.

Odpovědět
20.5.2013 11:12
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Petr Nymsa
Redaktor
Avatar
Odpovídá na Kit
Petr Nymsa:20.5.2013 11:22

V implementaci právě private / protected Set jsem musel dopsat, abych mohl vůbec property nastavit přes konstruktor. Zdá se mi to trochu neohrabaný , ale asi to takhle funguje

Odpovědět
20.5.2013 11:22
Pokrok nezastavíš, neusni a jdi s ním vpřed
Avatar
Kit
Redaktor
Avatar
Odpovídá na Petr Nymsa
Kit:20.5.2013 11:25

V implementaci vlastně může být cokoli, třeba nastavení konstanty nebo vložení jiného objektu už v deklaraci. Ten setter tam pak být nemusí.

Implementace totiž může práva rozšířit, ale nemůže je zúžit.

Editováno 20.5.2013 11:28
Odpovědět
20.5.2013 11:25
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Petr Čech
Redaktor
Avatar
Petr Čech:9.7.2013 15:09

jak se píše ta nota?

Odpovědět
9.7.2013 15:09
the cake is a lie
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Petr Čech
Luboš Běhounek Satik:9.7.2013 15:24

ja je pisu pres levy alt + 13 a levy alt + 14
♪♫

Editováno 9.7.2013 15:24
Odpovědět
9.7.2013 15:24
https://www.facebook.com/peasantsandcastles/
Avatar
Petr Čech
Redaktor
Avatar
Petr Čech:9.7.2013 15:26

díky

Odpovědět
9.7.2013 15:26
the cake is a lie
Avatar
codiac
Člen
Avatar
codiac:6.9.2013 16:07

Po naklepání do klavesnice a probrání a vyzkoušení mi ale připadne jako velmi zbytečné implementovat třídu PtakoJester: IJester, Ptak. Proč protože to funguje i bez implementace a navíc je přece blbost psát stejný kod s vyjímkou jedné metody jako je u tříd Ptak a Ptakojester. Uniká mi tedy smysl. Já přece nechci psát stejný kod dvakrát, vždyt to je podstata OOP, psát ho jednou! Při opravě pak nasekám tunu chyb.

 
Odpovědět
6.9.2013 16:07
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na codiac
Jan Vargovský:6.9.2013 17:02

Kde píšeš 2x stejný kód ? Btw ten kód ani nezkompiluješ, když třída, která má implementovat nějaké rozhraní ho neimplementuje.

Editováno 6.9.2013 17:03
 
Odpovědět
6.9.2013 17:02
Avatar
codiac
Člen
Avatar
Odpovídá na Jan Vargovský
codiac:6.9.2013 18:04

Soubor Ptak osahuje kod

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

public void Pipni()
{
Console.Write­Line("♫ ♫♫ ♫ ♫ ♫♫");
}

Proč se to znova opakuje v souboru PtakoJester plus
public void PlazSe()
{
Console.Write­Line("Plazím se...");
}

Editováno 6.9.2013 18:05
 
Odpovědět
6.9.2013 18:04
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na codiac
Jan Vargovský:6.9.2013 18:11

Je to jen příklad, ve skutečném příkladě by byly ty implementace různé. Kdybys nechtěl ten kód opakovat(měnit), tak by jsi zdědil PtakoJestera jen z ptáka a k tomu přidal ten interface IPtakoJester.

 
Odpovědět
6.9.2013 18:11
Avatar
codiac
Člen
Avatar
codiac:6.9.2013 18:16

Více násobnou dědičnost si představuji tak že pokud mám:
Základní skupinu 1. Zvire
Odvozená skupina I řádu 2. Pták a Ješter
Odvozena skupina II řádu 3. PtakoJešter, která výchází z toho že pták i ještěr zdědili vlastnosti nebo metody po zvířeti tudíž stačí implementovat ke tříde jen :Ptak, Jester.
Prostě mám základní kámen od kterého se to všechno odvíjí a nemusím přemýšlet nad tím jestli to zvíře dýchá protože je to automatické, bez toho zvíře nežije a proto by měl být řařen Dychej() ve zvířeti a u dvozených(v děděných) je to automaticky.

 
Odpovědět
6.9.2013 18:16
Avatar
codiac
Člen
Avatar
Odpovídá na codiac
codiac:6.9.2013 18:18

Makám na té kombinaci celý den, nějak se furt k tomu nemužu dobrat.

Mám interface na všechny skupiny plus přidaná třída Jester, ale je to problém.

Editováno 6.9.2013 18:20
 
Odpovědět
6.9.2013 18:18
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na codiac
Jan Vargovský:6.9.2013 18:28

Tohle není celá dědičnost, patří tam ještě abstraktní a virtuální metody, takže jestli chápeš jak vše funguje, tak potom později se ti to už bude implementovat lépe. Interface ti pomáhá narvat objekty do nějaké kolekce a pracovat se všema stejně, ať už je to pták nebo ještěr, obadva mají metodu Dýchej a to je to, co tě zajímá. Takhle natom příkladu nevidíš tu efektivnost. Takže jestli vše chápeš, pustil bych se vpohodě dál.

Editováno 6.9.2013 18:28
 
Odpovědět
6.9.2013 18:28
Avatar
codiac
Člen
Avatar
Odpovídá na Jan Vargovský
codiac:6.9.2013 18:31

Aha, tak díky :-)

 
Odpovědět
6.9.2013 18:31
Avatar
Odpovídá na codiac
miroslav.siska:30.10.2013 16:24

Ja to také nechapu. Respektive: Naimplementoval bych si tridu Ptak a Jester. Dále vytvorim rozhrani pro Ptak a Jester. A nasledne vytvorim Ptakojestera zdedenim z iPtak a iJester (to jsou interface). V programu vytvorim instanci Ptakojester a pak mohu volat metody jak z iPtaka tak z iJestera. Chapu to spravne? Pokud ano, tak je program spatne, jelokoz dvakrát implementuje stejne metody u ptaka i jestera v interface a zaroven kde je pro interface Ijester vytvorena zakladni trida? Je tam "bordel." Souhlasi to? Chapu spravne? Díky

 
Odpovědět
30.10.2013 16:24
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na miroslav.siska
Jan Vargovský:30.10.2013 16:39
Ptakojester a pak mohu volat metody jak z iPtaka tak z iJestera. Chapu to spravne?

Ano chápeš to správně. Jen kdybys koukl do toho kódu, tak bys zjistil, že ty tu metodu máš implementovanou jen jednou (v tom ptakojesterovi) a je jedno, skrz jaké rozhraní s ním spolupracuješ, protože impmelentuje jak IPtaka tak IJestera.

Na příkladu, když by si pracoval s tou jednou instancí ptakojestera takhle:

Ptakojeser pj = new Ptakojester();
// a můžeš s ním pracovat jako s ptakem nebo s jesterem
(pj as IPtak).Dychej();
// nebo
(pj as IJester).Dychej();

A obadva ti zavolají ten samý kód, akorát snima komunikuješ skrz jinačí rozhraní (protože ptakojester implementuje oboje, tak máš tu možnost)

Klidně potom v programu můžeš vytvořit

IPtak ptak = new Ptakojester();
IJester jester = new Ptakojester();

A pak víš, že obadva mají implementovanou metodu Dychej, ale IPtak implementuje Pipni a IJester PlazSe

Proto můžeš zavolat toto:

ptak.Dychej();
ptak.Pipni();
jester.Dychej();
jester.PlazSe();

Ale nemůžeš zavolat toto:

ptak.PlazSe();
jester.Pipni();
 
Odpovědět
30.10.2013 16:39
Avatar
miroslav.siska:30.10.2013 17:46

Chápu: (pj as IPtak).Dychej(); To jsem potřeboval :D Nešlo mi volat tyto původní metody... Jen mi šlo volat z class Ptakojester, kde bylo zase Pipni() znovu, ale jiné oproti class Ptak :D Vlastně byla metoda Pipni() z Ptak přepsaná v class Ptakojester... Postrádal jsem pak smysl proc se to dedí, když to vlastné nejde zavolat... Nakonec jsem vytvoril místo class Ptakojester interface Ptakojester: IPtak, IJester a šlo mi zavolat vše z Iptak i IJester pomocí instance Ptakojester ptakojester = new Ptakojester();... Děkuji za tyhle tutoriály. Je to super. P.S.: Když to "as" v (pj as IPtak) nebude vysvětlené později zase se poptám :D :D

 
Odpovědět
30.10.2013 17:46
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na miroslav.siska
Jan Vargovský:30.10.2013 18:21

Jednoduše pracuješ s proměnnou pj jako když je to objekt IPtak. To rozhraní ptakoještěr je celkem zavádějící, stačí když v definici třídy Ptakojester zdědíš oboje interface (IPtak, IJester) a nemusíš je složitě bez další implementace spojovat do IPtakojester.

Jinak to přetypování (pj as IPtak) jde napsat i takto

((IPtak)pj).Dychej();

To, že je ten kód nakopírovaný nic neznamená. Klidně můžeš mít Ptakojester : Ptak, IJester a doimplementuješ si jen tu metodu PlazSe ... Ale pak už jsi závislý (zkušenější neberte to doslova) na tom ptákovi, že ty ostatní metody změníš a budou dělat to samé jako u ptáka.

 
Odpovědět
30.10.2013 18:21
Avatar
miroslav.siska:30.10.2013 18:52

Díky.

 
Odpovědět
30.10.2013 18:52
Avatar
iximfo
Člen
Avatar
iximfo:4.7.2014 16:11

Vím že to sem nepatří ale ono nejde nahrávat programy do zdrojákoviště bez redaktorských práv.

 
Odpovědět
4.7.2014 16:11
Avatar
EfKá
Člen
Avatar
EfKá:14.9.2014 13:26

Čau, můžu se zeptat proč se metody pro dýchání a pípání doimplementovávají v ptakoještěrovi, když už jsou jednou implementovány v ptákovi? Myslel jsem, že prostě ptakoještěr přebere metody z rozhraní IPtak a IJester, tak proč je implementovat znova v ptakoještěrovi? Díky za odpověď.

 
Odpovědět
14.9.2014 13:26
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na EfKá
Jan Vargovský:14.9.2014 15:24

Rozhraní nic neimplementuje, jen říká jakým způsobem můžeš komunikovat s tím objektem, ale interface nikdy nemá žádnou implementaci, jen holé signatury.

 
Odpovědět
14.9.2014 15:24
Avatar
EfKá
Člen
Avatar
Odpovídá na Jan Vargovský
EfKá:15.9.2014 9:14

Ano, to vím. Ale já myslel to, že metody Dychej() a Pipni() jsou implementovány ve třídě Ptak a pak se znova implementují ve třídě Ptakojester. Proč, když už jsou implementovány jednou ve třídě Ptak?

 
Odpovědět
15.9.2014 9:14
Avatar
EfKá
Člen
Avatar
Odpovídá na Jan Vargovský
EfKá:15.9.2014 9:27

"přebere metody z rozhraní IPtak a IJester" jsem samozřejmě napsal nešťastně, myslel jsem PŘES rozhraní IPtak a IJEster.

 
Odpovědět
15.9.2014 9:27
Avatar
EfKá
Člen
Avatar
EfKá:15.9.2014 10:49

Nevšiml jsem si starších komentářů, teď už jsem to pochopil podle komentáře s příkladem přihlašování přes facebook, google atd. I tak díky :)

 
Odpovědět
15.9.2014 10:49
Avatar
NeonMaster
Člen
Avatar
NeonMaster:14.2.2015 23:00

Však to tam stejně napíšu ty metody do ptakojester proč to tam vubec vytvařet když stejně je potřeba to ve třídě ptakojester znova napsat co to dělá ta metoda... 8|

Editováno 14.2.2015 23:01
 
Odpovědět
14.2.2015 23:00
Avatar
hanpari
Redaktor
Avatar
Odpovídá na NeonMaster
hanpari:15.2.2015 7:34

Nejspis proto, ze c.# nepodporuje vicenasobnou dedicnost.

 
Odpovědět
15.2.2015 7:34
Avatar
NeonMaster
Člen
Avatar
Odpovídá na hanpari
NeonMaster:15.2.2015 10:10

Aha... ale výše je napsane že se to da obejit pres interface pritom neni zadny rozdil mezitim jestli tam ty interface vytvořim nebo ne..

 
Odpovědět
15.2.2015 10:10
Avatar
hanpari
Redaktor
Avatar
Odpovídá na NeonMaster
hanpari:15.2.2015 14:11

Právě teď to asi nemá velký smysl. Ale dejme tomu, že v budoucnu budeš mít nějaký objekt a jediné, co budeš potřebovat, je mít jistotu, že nějakým způsobem dejme tomu implementuje rozhraní IPtak, protože budeš potřebovat, aby ten objekt pípnul. A nebude tě zajímat, zda je to pták nebo polopták.

OOP je o tom, že se snažíš přemýšlet hodně hodně dopředu :)

 
Odpovědět
15.2.2015 14:11
Avatar

Člen
Avatar
Odpovídá na Jan Vargovský
:29.9.2015 17:13

Na komentář "...jelokoz dvakrát implementuje stejne metody.." od miroslav.siska si reagoval, že "..tu metodu máš implementovanou jen jednou..". Přišlo mi to trochu zmatené, a tak jsem si ten kód prošel ještě jednou a jestli to tedy chápu, v tom původním příkladě (třída Ptak a rozhraní IPtak) došlo k implementaci metody Dychej() u IPtak tímto kódem

IPtak ptak = new Ptak();

Dá se to tak říct?

 
Odpovědět
29.9.2015 17:13
Avatar

Člen
Avatar
:20.10.2015 20:46

hanpari: Omlouvám se, zase nevratitelný dislike..

 
Odpovědět
20.10.2015 20:46
Avatar
Pavel Štumpf:7.11.2015 10:56

Super článek, děkuji.

 
Odpovědět
7.11.2015 10:56
Avatar
Pavel Štumpf:7.11.2015 11:25

Chtěl bych se zeptat, jestli je nutné v programu explicitně definovat daný interface. Studuji teď jeden program a tam se používá dědění z interface, ale takto explicitně definované interface:

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

naprosto chybí, ale program přesto nehlásí chybu. Je možné, že je definováno v jiné části prgramu? Zdroják bohužel nemohu sdílet. Díky za případnou odpověď.

 
Odpovědět
7.11.2015 11:25
Avatar
Odpovídá na Pavel Štumpf
Pavel Štumpf:7.11.2015 12:08

Ok, tak jsem právě objevil metadata, kde je interface definováno :-)

 
Odpovědět
7.11.2015 12:08
Avatar
Štefan Pružinský:13.2.2016 16:50

Ďakujem za výborný článok. :)

Odpovědět
13.2.2016 16:50
Najefektívnejším spôsobom debuggingu je modlitba. :)
Avatar
Honza.G
Člen
Avatar
Honza.G:24.7.2016 9:30

Zdravím :) chtěl bych se zeptat, ty metody mám doiplementovat tak že je dopíšu klasicky: " console....." Nebo je nato nějakej fígl? po importaci tam mám to: "throw new" a ještě v nabídce mi to nenabízí všechny ty metody. Předem dík moc :)

 
Odpovědět
24.7.2016 9:30
Avatar
Honza Rada
Člen
Avatar
Honza Rada:6.5.2017 7:00

Ďěkujem za super článek

Odpovědět
6.5.2017 7:00
#c#
Avatar
David Draisaitl:11.9.2017 15:33

Jakým způsobem lze doimplementovat implementované metody, ať se mi vypíšou kompletní :)?

 
Odpovědět
11.9.2017 15:33
Avatar
Odpovídá na David Draisaitl
Martin Turner:18.9.2017 6:51

Ahoj Davide,

jak to myslíš?
Jak je uvedeno ve článku, Visual studio ti nabízí možnost vytvoření metod, které musí třída (díky dědění z interface) obsahovat - pomocí Implement Interface.
Obsah metody (co bude přesně dělat) už si doplníš sám. Hláška (výjimka) throw new NotImplemente­dException(); tě upozorňuje, že je metodu potřeba dodefinovat, nemůže zůstat prázdná.

 
Odpovědět
18.9.2017 6:51
Avatar
Odpovídá na Martin Turner
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.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.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.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ěď.

 
Odpovědět
4.7.2018 20:29
Avatar
Odpovídá 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.

Odpovědět
4.7.2018 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.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.

 
Odpovědět
4.7.2018 20:45
Avatar
Odpovídá na Milan
Michal Šmahel:4.7.2018 20:56

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

Odpovědět
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. května 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

 
Odpovědět
2. května 10:55
Avatar
David Jančík
Tým ITnetwork
Avatar
Odpovídá na Michael K.
David Jančík:2. května 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í.

Odpovědět
2. května 11:30
Zapomeň, že je to nemožné a udělej to ;)
Avatar
Michael K.
Člen
Avatar
Michael K.:2. května 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?

Editováno 2. května 11:37
 
Odpovědět
2. května 11:36
Avatar
vosa53
Člen
Avatar
Odpovídá na Michael K.
vosa53:2. května 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
 
Odpovědět
2. května 14:12
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 65 zpráv z 65.