NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze – Lekce 7 - Dědičnost a polymorfismus

Zpět

Upozorňujeme, že diskuze pod našimi online kurzy jsou nemoderované a primárně slouží k získávání zpětné vazby pro budoucí vylepšení kurzů. Pro studenty našich rekvalifikačních kurzů nabízíme možnost přímého kontaktu s lektory a studijním referentem pro osobní konzultace a podporu v rámci jejich studia. Toto je exkluzivní služba, která zajišťuje kvalitní a cílenou pomoc v případě jakýchkoli dotazů nebo projektů.

Komentáře
Avatar
Lukáš Hruda
Tvůrce
Avatar
Odpovídá na MS84
Lukáš Hruda:11.6.2015 10:25

Konstruktory se nedědí.

 
Odpovědět
11.6.2015 10:25
Avatar
Majký
Člen
Avatar
Majký:27.1.2016 8:54
Uzivatel u = new Uzivatel("Jan Novák", 33);
Administrator a = new Administrator("Josef Nový", 25);
// Nyní do uživatele uložíme administrátora:
u = a;
// Vše je v pořádku, protože uživatel je předek
// Zkusíme to opačně a dostaneme chybu:
a = u;

Ahoj,

  1. jak můžů do uživatele uložit administrátota, vždyť má víc atributů (telefonniCislo). Naopak a=u bych pochopil s tím, že telefonniCislo bude null. Asi mám špatnou představu, že jsou to "tabulky s různou strukturou" a do menší tu větší prostě nedám :(
  2. is to rozeznává(jestli je to předek nebo potomek) podle použitého konstruktoru?
 
Odpovědět
27.1.2016 8:54
Avatar
Jindřich Máca
Tvůrce
Avatar
Odpovídá na Majký
Jindřich Máca:27.1.2016 21:12

Ahoj, zkusím to trochu objasnit. :)

  1. No, představa objektů jako "tabulek s různou strukturou" je docela zavádějící. Jde o to, že přiřazení Uzivatel do Administrator by Ti nepřineslo v podstatě žádný užitek, jelikož např. administrátora, kde telefonniCislo je null si můžeš vytvořit ručně taky. Navíc, jak by jsi volal metody, které Administrator má a Uzivatel ne? Když ale přiřadíš Administrator do Uzivatel můžeš se k němu chovat jako k uživateli s tím, že pro dané metody může například vykonávat něco jiného než Uzivatel jako takový. Tohle chování v důsledku tvoří základ polymorfismu, o kterém je v článku také řeč. Samozřejmě pak platí, že tímto přiřazením se odřízneš od toho, co má Administrator navíc od Uzivatel, ale to v místě, kde se k němu chceš chovat jako k uživateli vlastně vůbec nevadí. :)
  2. is je klíčové slovo jazyka a uvnitř tak může fungovat všelijak. S jeho vnitřní architekturou bych si tady moc nelámal hlavu, důležité je vědět, co dělá (viz. https://msdn.microsoft.com/…cekt9xw.aspx). ;)

Doufám, že jsem to popsal dostatečně jasně, když tak se ještě ptej. :)

 
Odpovědět
27.1.2016 21:12
Avatar
Petr Panský :30.12.2016 19:40

Ahoj, našla by se nějaká dobrá duše, která by mi někam dala vypracovaný tento úkol? Chápu princip, ale potřeboval bych vidět jak to má fungovat se všemi věcmi, které jsou vynechané. Pokud se někdo najde, budu moc rád :)
Děkuji :)

 
Odpovědět
30.12.2016 19:40
Avatar
Martin Tomko
Člen
Avatar
Martin Tomko:6.2.2017 20:10

Ahojte.
Zaujímalo ma, ako sa bude správať program, keď nezmením v triede Uzivatel atribúty z private na protected. Na moje počudovanie to programu vôbec nevadí a vo vytvorenej inštancii Administratora viem s privátnymi atribútmi Uzivatela pracovať. Prikladám časť spomínaného kódu:

class Uzivatel
{
private string meno = "Jozef";
private string priezvisko = "Nový";
private int vek = 25;

public override string ToString()
{
return String.Format("{0} {1} {2}", meno, priezvisko, vek);
}
...
}

class Program
{
static void Main(string[] args)
{
Administrator a = new Administrator();
Console.Write­Line(a);
Console.ReadKey();
}
}

Dokonca aj keď som si vytvoril konštruktory v triede Uzivatel aj Administrator, tak som vedel pri inštancovaní Administratora nastaviť privátne atribúty definované v Uzivatelovi. Prečo je to tak? Bude sa ten rozdiel prejavovať niekde inde?

Ďakujem.

 
Odpovědět
6.2.2017 20:10
Avatar
Odpovídá na Jindřich Máca
Michaela Radimská:3.3.2018 13:12

Ahoj, můžeš mi prosím vysvětlit k bodu 1, jestli se to reálně využívá, kdy a proč? Fungování jsem snad celkem pochopila a vyzkoušela.

 
Odpovědět
3.3.2018 13:12
Avatar
Michaela Radimská:3.3.2018 13:17

Ještě doplňuji, že jde o příspěvek z roku 2016, cituji úsek, který mne zajímá:

Cituji:
"Když ale přiřadíš Administrator do Uzivatel můžeš se k němu chovat jako k uživateli s tím, že pro dané metody může například vykonávat něco jiného než Uzivatel jako takový. Tohle chování v důsledku tvoří základ polymorfismu, o kterém je v článku také řeč. Samozřejmě pak platí, že tímto přiřazením se odřízneš od toho, co má Administrator navíc od Uzivatel, ale to v místě, kde se k němu chceš chovat jako k uživateli vlastně vůbec nevadí. :)"

 
Odpovědět
3.3.2018 13:17
Avatar
Jindřich Máca
Tvůrce
Avatar
Odpovídá na Michaela Radimská
Jindřich Máca:3.3.2018 18:49

Zdravím! Polymorfismus, obzvláště ve staticky typovaným jazycích jako je C#, např. ještě v kombinaci s rozhraním nebo abstraktní třídou, je velice mocným nástrojem a má mnoho praktických využití. Takový jednoduchý příklad je již nastíněn i v článku, kde můžeme vzít instance tříd různých zvířat a uložit je všechny do jediného pole typu třídy zvířete, ze které tyto třídy zvířat dědí. Takový hodně zjednodušený kód tohoto by mohl vypadat následovně:

// Třída zvířete.
class Zvire
{
    public virtual string VydejZvuk()
    {
         return "";
    }
}

// Třídy jeho potomků.
class Pes : Zvire
{
    public override string VydejZvuk()
    {
        return "Woof";
    }
}

class Kocka : Zvire
{
    public override string VydejZvuk()
    {
        return "Meow";
    }
}

class Kachna : Zvire
{
    public override string VydejZvuk()
    {
        return "Quack";
    }
}

// Hlavní program ve funkci Main.
Zvire[] zvirata =  {new Pes(),  new Kocka(),  new Kachna()};

foreach (Zvire zvire in zvirata)
{
    Console.WriteLine(zvire.VydejZvuk());
}

Na výstupu podle očekávání vydá popořadě každé zvíře svůj zvuk "Woof", "Meow", "Quack", ale všechny jsou uloženy ve stejném poli pro lepší hromadnou manipulaci.

Doufám, že teď už je to lépe představitelné. Podobné, samozřejmě složitější konstrukce mají v praxi široké uplatnění. ;)

 
Odpovědět
3.3.2018 18:49
Avatar
Odpovídá na Jindřich Máca
Michaela Radimská:3.3.2018 19:28

Děkuji za odpověď, ale asi jsem se špatně zeptala. Šlo mi o případ, který jsi tam vysvětloval:

Uzivatel u = new Administrator("Jo­sef Nový", 25);

s komentářem:
"Samozřejmě pak platí, že tímto přiřazením se odřízneš od toho, co má Administrator navíc od Uzivatel, ale to v místě, kde se k němu chceš chovat jako k uživateli vlastně vůbec nevadí."

Nejsem si jistá, proč ho neimplementovat jako administrátora, tj. kdy se to smysluplně využije (zřejmě chci použít přepsané metody, ale nedovolit mu něco, co smí administrátor a nesmí uživatel?) - nenapadá mne reálná situace, ta mne zajímala. Díky :-)

 
Odpovědět
3.3.2018 19:28
Avatar
Martin Petrovaj
Tvůrce
Avatar
Martin Petrovaj:3.3.2018 20:36

Možno by som niečo dodal aj ja:

Scenár 1: Predstavme si, že máme napr. nejakú grafickú, kresliacu aplikáciu, ktorej súčasťou je canvas (kresliaca plocha). Na nej sú rozmiestnené rôzne užívateľom vytvorené objekty - čiary, obdĺžniky, elipsy… ktoré všetky dedia z abstraktnej triedy GeometrickyUtvar, ktorá obsahuje aj vlastnosť Poloha. Užívateľ myšou označí viacero rôznych útvarov a chce ich potiahnutím naraz presunúť niekam vedľa.

foreach (GeometrickyUtvar utvar in oznaceneObjekty)
{
        utvar.Poloha = mys.Poloha + offset;
}

Užívateľ v tomto prípade mohol označiť čokoľvek - elipsu, text, kruh - nás to ale nezaujíma, nepotrebujeme funkcionalitu rozdielnych objektov, chceme nám len zmeniť ich polohu. Stačí nám s nimi teda pracovať ako s inštanciami triedy GeometrickyUtvar. Konieckoncov, snažiť sa predpovedať, aké druhy objektov používateľ označí nedáva veľmi zmysel a nie je to ani potrebné :-)

Scenár 2: Predstavme si jednoduchú akčnú hru, kde máme triedy Nepriatel implementujúcu metódu Zomri a triedu StraslivyNepriatel, ktorá z Nepriatel dedí. Keďže StraslivyNepriatel je ale taký výrazne vzácnejší a náročnejší nepriateľ, budeme mu chcieť pridať nejaké zvláštne efekty pri smrti, aby mal hráč lepší pocit z víťazstva :-) (napr. predsmrtný výkrik, výbuchy v okolí a pod.). V hre máme naskriptovaný event, ktorý počas misie (zrejme pri nejakej zvláštnej udalosti alebo cutscéne) zabije skupinu nepriateľov - aj bežných, aj "strašlivých".

class Nepriatel
{
        //…

        virtual public void Zomri()
        {
                nazive = false;
                PrehrajAnimaciu( this.animaciaSmrti );
                //…
        }
}
class StraslivyNepriatel : Nepriatel
{
        //…

        override public void Zomri()
        {
                nazive = false;
                SpawniVybuchy();
                PrehrajZvuk( this.revPredSmrtou );
                PrehrajAnimaciu( this.animaciaSmrti );
                //…
        }
}
foreach (Nepriatel nepriatel in zasiahnutiNestastnici)
{
        nepriatel.Zomri();      // pouzije spravnu implementaciu ako pre Nepriatel, tak aj pre StraslivyNepriatel
}

Pokiaľ v oddedenej triede preťažíme virtuálnu metódu slovíčkom override, zavolá sa táto preťažená metóda aj v situácii, keď s inštanciou pracujeme ako s jej predkom (napr. ak pracujeme s inštanciou StraslivyNepriatel ako keby to bol Nepriatel).
Ak by sme chceli dosiahnuť opačné chovanie (použiť implementáciu používaného typu bez ohľadu na to, o aký objekt sa v skutočnosti jedná), použili by sme v potomkovi namiesto override slovíčko new.

Pravdaže, reálne by sa obidve tieto situácie mohli a asi aj riešili inak, ale tu sú použité len ako ukážky na vysvetlenie O:-)

Odpovědět
3.3.2018 20:36
if (this.motto == "") { throw new NotImplementedException(); }
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 47.