Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Jazyk C# je navržený tak, aby se správa verzí mezi základní a odvozenou sadou v různých knihovnách vyvinula a zachovala zpětnou kompatibilitu. To například znamená, že zavedení nového člena do základní třídy se stejným názvem jako člen v odvozené třídě je plně podporováno jazykem C# a nemá za následek neočekávané chování. Také to znamená, že třída musí explicitně uvést, zda je metoda určena k přepsání zděděné metody, nebo zda metoda je nová metoda, která skryje podobně pojmenovanou zděděnou metodu.
V jazyce C# mohou odvozené třídy obsahovat metody se stejným názvem jako metody základní třídy.
Pokud metodě v odvozené třídě nepředcházejí klíčová slova new nebo override, kompilátor vydá upozornění a metoda se bude chovat, jako by bylo klíčové slovo
newpřítomné.Pokud je metoda v odvozené třídě před klíčovým slovem
new, metoda je definována jako nezávislá na metodě v základní třídě.Pokud je metoda v odvozené třídě před klíčovým slovem
override, objekty odvozené třídy budou volat tuto metodu namísto metody základní třídy.Aby bylo možné použít
overrideklíčové slovo na metodu v odvozené třídě, musí být metoda základní třídy definována virtuální.Metodu základní třídy lze volat z odvozené třídy pomocí klíčového
baseslova.Klíčová slova
override,virtualanewlze také použít pro vlastnosti, indexery a události.
Ve výchozím nastavení nejsou metody jazyka C# virtuální. Pokud je metoda deklarována jako virtuální, může každá třída dědící metodu implementovat vlastní verzi. Chcete-li vytvořit metodu virtuální, virtual modifikátor se používá v deklaraci metody základní třídy. Odvozená třída pak může přepsat základní virtuální metodu pomocí klíčového override slova nebo skrýt virtuální metodu v základní třídě pomocí klíčového new slova. Pokud není klíčové slovo override ani klíčové slovo new zadáno, kompilátor vydá upozornění a metoda v odvozené třídě skryje metodu v základní třídě.
Abychom to ukázali v praxi, předpokládejme, že společnost A vytvořila třídu s názvem GraphicsClass, kterou program používá. Následuje:GraphicsClass
class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
}
Vaše společnost tuto třídu používá ke svým účelům, zatímco vy ji využíváte k odvození vlastní třídy a přidání nové metody.
class YourDerivedGraphicsClass : GraphicsClass
{
public void DrawRectangle() { }
}
Vaše aplikace se používá bez problémů, dokud společnost A uvolní novou verzi GraphicsClass, která se podobá následujícímu kódu:
class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
public virtual void DrawRectangle() { }
}
Nová verze GraphicsClass nyní obsahuje metodu s názvem DrawRectangle. Zpočátku se nic nestává. Nová verze je stále binární kompatibilní se starou verzí. Veškerý software, který jste nasadili, bude fungovat i v případě, že je v těchto počítačových systémech nainstalována nová třída. Všechna existující volání metody DrawRectangle budou nadále odkazovat na vaši verzi v odvozené třídě.
Jakmile však aplikaci znovu zkompilujete pomocí nové verze GraphicsClass, obdržíte upozornění z kompilátoru CS0108. Toto upozornění vás informuje, že musíte zvážit, jak se má vaše DrawRectangle metoda chovat ve vaší aplikaci.
Pokud chcete, aby vaše metoda přepsala novou metodu v základní třídě, použijte klíčové slovo override.
class YourDerivedGraphicsClass : GraphicsClass
{
public override void DrawRectangle() { }
}
Klíčové override slovo zajišťuje, že všechny objekty odvozené z YourDerivedGraphicsClass budou používat odvozenou třídu verze DrawRectangle. Objekty odvozené z YourDerivedGraphicsClass můžou dál přistupovat k verzi DrawRectangle základní třídy pomocí základního klíčového slova:
base.DrawRectangle();
Pokud nechcete, aby vaše metoda přepsala novou metodu základní třídy, platí následující aspekty. Abyste se vyhnuli nejasnostem mezi těmito dvěma metodami, můžete metodu přejmenovat. To může být časově náročné a náchylné k chybám a v některých případech to není praktické. Pokud je ale projekt relativně malý, můžete metodu přejmenovat pomocí možností refaktoringu sady Visual Studio. Další informace najdete v tématu Refaktoring tříd a typů (Návrhář tříd).
Případně můžete zabránit upozornění použitím klíčového slova new v definici odvozené třídy:
class YourDerivedGraphicsClass : GraphicsClass
{
public new void DrawRectangle() { }
}
Použití klíčového new slova říká kompilátoru, že definice skryje definici obsaženou v základní třídě. Toto je výchozí chování.
Přepsání a výběr metody
Pokud je metoda pojmenována ve třídě, kompilátor jazyka C# vybere nejlepší metodu volání, pokud je více než jedna metoda kompatibilní s voláním, například pokud existují dvě metody se stejným názvem a parametry, které jsou kompatibilní s předaným parametrem. Následující metody by byly kompatibilní:
public class Derived : Base
{
public override void DoWork(int param) { }
public void DoWork(double param) { }
}
Při volání DoWork na instanci Derived se kompilátor jazyka C# nejprve pokusí provést volání tak, aby bylo kompatibilní s verzemi DoWork původně deklarovanými na Derived. Metody přepsání se neberou jako deklarované v rámci třídy; jedná se o nové implementace metod deklarovaných v základní třídě. Pouze pokud kompilátor jazyka C# nedokáže sladit volání metody s původní metodou na Derived, pokusí se sladit toto volání s přepsanou metodou se stejným názvem a kompatibilními parametry. Například:
int val = 5;
Derived d = new();
d.DoWork(val); // Calls DoWork(double).
Vzhledem k tomu, že proměnnou val lze implicitně převést na typ double, kompilátor jazyka C# volá DoWork(double) namísto DoWork(int). Existují dva způsoby, jak se tomu vyhnout. Nejprve se vyhněte deklarování nových metod se stejným názvem jako virtuální metody. Za druhé, můžete dát kompilátoru jazyka C# pokyn, aby volal virtuální metodu tím, že prohledá seznam metod základní třídy přetypováním instance Derived na Base. Vzhledem k tomu, že metoda je virtuální, bude volána implementace na DoWork(int) a Derived. Například:
((Base)d).DoWork(val); // Calls DoWork(int) on Derived.
Pro další příklady new a override, viz Kdy použít přetížení a nová klíčová slova.