Verziószámozás felülbírálással és új kulcsszavakkal (C# programozási útmutató)
A C#-nyelv úgy lett kialakítva, hogy a különböző kódtárak alap- és származtatott osztályai közötti verziószámozás fejlődjön, és fenntarthassa a visszamenőleges kompatibilitást. Ez például azt jelenti, hogy a C# teljes mértékben támogatja egy új tag bevezetését egy alaposztályban, amelynek neve megegyezik egy származtatott osztály tagjával, és nem vezet váratlan viselkedéshez. Azt is jelenti, hogy az osztálynak explicit módon meg kell állapítania, hogy egy metódus egy örökölt metódus felülbírálására szolgál-e, vagy egy metódus egy új metódus, amely elrejt egy hasonlóan elnevezett öröklött metódust.
A C#-ban a származtatott osztályok olyan metódusokat tartalmazhatnak, amelyek neve megegyezik az alaposztály-metódusokkal.
Ha a származtatott osztály metódusát nem előzi meg új vagy felülbíráló kulcsszavak, a fordító figyelmeztetést ad ki, és a metódus úgy fog viselkedni, mintha a
new
kulcsszó jelen lett volna.Ha a származtatott osztály metódusát megelőzi a
new
kulcsszó, a metódus az alaposztály metódusától függetlenként van definiálva.Ha a származtatott osztály metódusát megelőzi a
override
kulcsszó, a származtatott osztály objektumai az alaposztály metódusa helyett ezt a metódust hívják meg.Ahhoz, hogy a kulcsszót
override
a származtatott osztály metódusára alkalmazza, az alaposztály metódusát virtuálisan kell definiálni.Az alaposztály metódusa meghívható a származtatott osztályból a
base
kulcsszó használatával.A
override
,virtual
és a kulcsszavak tulajdonságokra, indexelőkre ésnew
eseményekre is alkalmazhatók.
Alapértelmezés szerint a C# metódusok nem virtuálisak. Ha egy metódus virtuálisként van deklarálva, a metódust öröklő bármely osztály implementálhatja a saját verzióját. A metódus virtuálissá tételéhez a virtual
módosító az alaposztály metódusdeklarációjában használatos. A származtatott osztály ezután felülbírálhatja az alapszintű virtuális metódust a override
kulcsszó használatával, vagy elrejtheti a virtuális metódust az alaposztályban a new
kulcsszó használatával. Ha sem a override
kulcsszó, sem a new
kulcsszó nincs megadva, a fordító figyelmeztetést ad ki, és a származtatott osztály metódusa elrejti a metódust az alaposztályban.
Ennek a gyakorlatban való bemutatásához tegyük fel, hogy az A vállalat létrehozott egy osztályt GraphicsClass
, amelyet a program használ. A következők:GraphicsClass
class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
}
A vállalat ezt az osztályt használja, ön pedig saját osztályt hoz létre, új metódus hozzáadásával:
class YourDerivedGraphicsClass : GraphicsClass
{
public void DrawRectangle() { }
}
Az alkalmazás problémamentesen használható, amíg az A vállalat nem ad ki egy új verziót GraphicsClass
, amely a következő kódhoz hasonlít:
class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
public virtual void DrawRectangle() { }
}
Az új verzió GraphicsClass
egy metódust DrawRectangle
tartalmaz. Kezdetben semmi sem történik. Az új verzió továbbra is binárisan kompatibilis a régi verzióval. Az üzembe helyezett szoftverek továbbra is működni fognak, még akkor is, ha az új osztály telepítve van ezeken a számítógépes rendszereken. A metódushoz DrawRectangle
intézett összes meglévő hívás továbbra is hivatkozni fog az Ön verziójára a származtatott osztályban.
Amint azonban az alkalmazás újrafordítása az új verzió GraphicsClass
használatával történik, figyelmeztetést kap a CS0108 fordítótól. Ez a figyelmeztetés arról tájékoztatja, hogy figyelembe kell vennie, hogyan szeretné, hogy a DrawRectangle
metódus az alkalmazásban viselkedjen.
Ha azt szeretné, hogy a metódus felülbírálja az új alaposztály-metódust, használja a következő kulcsszót override
:
class YourDerivedGraphicsClass : GraphicsClass
{
public override void DrawRectangle() { }
}
A override
kulcsszó gondoskodik arról, hogy a származtatott YourDerivedGraphicsClass
objektumok a származtatott osztályverziót DrawRectangle
használják. A származtatott YourDerivedGraphicsClass
objektumok továbbra is hozzáférhetnek az alaposztály verziójához DrawRectangle
az alapszintű kulcsszó használatával:
base.DrawRectangle();
Ha nem szeretné, hogy a metódus felülbírálja az új alaposztály-metódust, az alábbi szempontokat kell figyelembe vennie. A két módszer közötti félreértések elkerülése érdekében átnevezheti a metódust. Ez időigényes és hibalehetőséget jelenthet, és bizonyos esetekben nem praktikus. Ha azonban a projekt viszonylag kicsi, a Visual Studio újrabontási beállításaival átnevezheti a metódust. További információ: Osztályok és típusok újrabontása (Osztály Tervező).
Másik lehetőségként megakadályozhatja a figyelmeztetést a származtatott new
osztálydefiníció kulcsszójának használatával:
class YourDerivedGraphicsClass : GraphicsClass
{
public new void DrawRectangle() { }
}
new
A kulcsszó használatával a fordító közli, hogy a definíció elrejti az alaposztályban található definíciót. Ez az alapértelmezett viselkedés.
Felülbírálás és módszer kiválasztása
Ha egy metódus el van nevezve egy osztályban, a C#-fordító kiválasztja a legjobban meghívható metódust, ha több metódus is kompatibilis a hívással, például ha két azonos nevű metódus van, és az átadott paraméterrel kompatibilis paraméterek. A következő módszerek kompatibilisek lehetnek:
public class Derived : Base
{
public override void DoWork(int param) { }
public void DoWork(double param) { }
}
Amikor DoWork
a rendszer meghív egy példánytDerived
, a C#-fordító először megpróbálja kompatibilissé tenni a hívást az eredetileg Derived
deklarált verziókkalDoWork
. A felülbírálási metódusok nem minősülnek osztályon deklaráltnak, hanem egy alaposztályon deklarált metódus új implementációi. Csak akkor, ha a C#-fordító nem tud egyezni egy eredeti metódus Derived
metódushívásával, akkor megpróbál megegyezni egy felülírt metódussal ugyanazzal a névvel és kompatibilis paraméterekkel. Példa:
int val = 5;
Derived d = new Derived();
d.DoWork(val); // Calls DoWork(double).
Mivel a változót val
kettős implicit módon lehet konvertálni, a C#-fordító ahelyett DoWork(int)
hív megDoWork(double)
. Ezt kétféleképpen lehet elkerülni. Először is kerülje az új metódusok deklarálását a virtuális metódusokkal azonos néven. Másodszor utasíthatja a C#-fordítót, hogy hívja meg a virtuális metódust úgy, hogy az alaposztály metóduslistájában keres, ha a példányt a következőre Base
állítjaDerived
. Mivel a metódus virtuális, a rendszer meghívja DoWork(int)
Derived
a végrehajtást. Példa:
((Base)d).DoWork(val); // Calls DoWork(int) on Derived.
További példákat new
és override
példákat a Felülbírálás és új kulcsszavak használatának ismerete című témakörben talál.