Lekce 13: Dědičnost a polymorfismus – Rozšiřování tříd v C#
Dědičnost a polymorfismus jsou dva klíčové principy objektově orientovaného programování (OOP). Tyto koncepty umožňují efektivní organizaci kódu, jeho znovupoužitelnost a flexibilitu při rozšiřování funkcionalit. V této lekci si vysvětlíme, co znamená dědičnost a polymorfismus v C#, jak fungují, a ukážeme si, jak je používat v praxi.
1. Co je dědičnost?
Dědičnost umožňuje jedné třídě (tzv. odvozené třídě) přebírat vlastnosti a metody jiné třídy (tzv. základní třídy). Tento koncept umožňuje znovupoužití kódu a vytváření hierarchických vztahů mezi třídami.
- Základní třída (parent/base class): Definuje obecné vlastnosti a chování, které mohou být sdíleny odvozenými třídami.
- Odvozená třída (child/derived class): Rozšiřuje nebo přizpůsobuje chování základní třídy.
Příklad dědičnosti
public class Zvire
{
public string Jmeno { get; set; }
public void PredstavSe()
{
Console.WriteLine($"Jsem zvíře a jmenuji se {Jmeno}.");
}
}
// Odvozená třída
public class Pes : Zvire
{
public void StacejOhon()
{
Console.WriteLine($"{Jmeno} vrtí ocasem.");
}
}
V tomto příkladu třída Pes dědí vlastnosti a metody třídy Zvire. Můžeme tedy vytvořit instanci třídy Pes, která bude mít přístup k metodě PredstavSe ze základní třídy a zároveň k metodě StacejOhon definované v odvozené třídě.
Použití:
Pes mujPes = new Pes();
mujPes.Jmeno = "Rex";
mujPes.PredstavSe(); // Výstup: Jsem zvíře a jmenuji se Rex.
mujPes.StacejOhon(); // Výstup: Rex vrtí ocasem.
2. Klíčová slova base
a přepisování metod
Klíčové slovo base
Klíčové slovo base
umožňuje odvozené třídě přistupovat k metodám nebo konstruktorům základní třídy. Používá se pro:
- Volání konstruktoru základní třídy.
- Přístup k přetíženým metodám základní třídy.
Příklad volání konstruktoru:
public class Zvire
{
public string Jmeno { get; set; }
public Zvire(string jmeno)
{
Jmeno = jmeno;
Console.WriteLine($"Zvíře {Jmeno} bylo vytvořeno.");
}
}
public class Pes : Zvire
{
public Pes(string jmeno) : base(jmeno)
{
Console.WriteLine($"Pes {Jmeno} byl vytvořen.");
}
}
Použití:
Pes mujPes = new Pes("Rex");
// Výstup:
// Zvíře Rex bylo vytvořeno.
// Pes Rex byl vytvořen.
3. Přepisování metod a vlastností
Dědičnost umožňuje odvozené třídě přepsat metody nebo vlastnosti základní třídy. K tomu slouží klíčová slova virtual
, override
a sealed
.
virtual
: Označuje, že metoda nebo vlastnost v základní třídě může být přepsána.override
: Používá se v odvozené třídě k přepsání metody.sealed
: Brání dalšímu přepisování metody.
Příklad přepisování:
public class Zvire
{
public virtual void Zvuk()
{
Console.WriteLine("Zvíře vydává zvuk.");
}
}
public class Pes : Zvire
{
public override void Zvuk()
{
Console.WriteLine("Pes štěká.");
}
}
public class Kocka : Zvire
{
public override void Zvuk()
{
Console.WriteLine("Kočka mňouká.");
}
}
Použití:
Zvire mojeZvire = new Pes();
mojeZvire.Zvuk(); // Výstup: Pes štěká.
mojeZvire = new Kocka();
mojeZvire.Zvuk(); // Výstup: Kočka mňouká.
4. Co je polymorfismus?
Polymorfismus znamená, že objekty různých tříd mohou být zpracovávány stejným způsobem, pokud sdílejí stejný typ nebo rozhraní. To umožňuje volat metody na různých objektech, které mají různé implementace.
Typy polymorfismu
- Kompilátorový polymorfismus (přetížení metod): Více metod se stejným názvem, ale s různými parametry.
- Běhový polymorfismus (přepisování metod): Volání přepsané metody prostřednictvím odkazu na základní třídu.
Příklad polymorfismu:
public void ZahrajZvuk(Zvire zvire)
{
zvire.Zvuk();
}
Zvire pes = new Pes();
Zvire kocka = new Kocka();
ZahrajZvuk(pes); // Výstup: Pes štěká.
ZahrajZvuk(kocka); // Výstup: Kočka mňouká.
V tomto příkladu metoda ZahrajZvuk přijímá libovolný objekt typu Zvire a volá na něm metodu Zvuk. Díky polymorfismu každá třída poskytuje svou vlastní implementaci této metody.
5. Výhody dědičnosti a polymorfismu
- Znovupoužitelnost kódu: Obecné metody a vlastnosti jsou definovány pouze jednou v základní třídě.
- Flexibilita a rozšiřitelnost: Nové třídy mohou rozšiřovat funkcionalitu bez nutnosti úpravy existujícího kódu.
- Jednodušší správa: Změny v základní třídě se automaticky projeví v odvozených třídách.
6. Praktický příklad
Představme si aplikaci pro sledování různých typů vozidel:
public class Vozidlo
{
public string SPZ { get; set; }
public virtual void Jezdi()
{
Console.WriteLine("Vozidlo jede.");
}
}
public class Auto : Vozidlo
{
public override void Jezdi()
{
Console.WriteLine($"Auto s SPZ {SPZ} jede po silnici.");
}
}
public class Lod : Vozidlo
{
public override void Jezdi()
{
Console.WriteLine($"Loď s SPZ {SPZ} pluje po vodě.");
}
}
Použití:
Vozidlo auto = new Auto { SPZ = "1A2B3C" };
auto.Jezdi(); // Výstup: Auto s SPZ 1A2B3C jede po silnici.
Vozidlo lod = new Lod { SPZ = "XYZ123" };
lod.Jezdi(); // Výstup: Loď s SPZ XYZ123 pluje po vodě.
Závěr
Dědičnost a polymorfismus jsou klíčové koncepty pro budování flexibilních, rozšiřitelných a znovupoužitelných aplikací v C#. Dědičnost umožňuje definovat obecné chování v základních třídách a specifikovat jedinečné vlastnosti v odvozených třídách. Polymorfismus pak přináší možnost práce s objekty různých typů, které sdílejí stejnou základní třídu. Tyto principy společně tvoří základ pro efektivní objektově orientovaný design.