Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Język C# został zaprojektowany tak, aby zarządzanie wersjami między klasami podstawowymi i pochodnymi w różnych bibliotekach mogło ewoluować i zachowywać zgodność wsteczną. Oznacza to na przykład, że wprowadzenie nowego elementu członkowskiego w klasie bazowej o takiej samej nazwie jak składowa w klasie pochodnej jest całkowicie obsługiwane przez język C# i nie prowadzi do nieoczekiwanego zachowania. Oznacza to również, że klasa musi jawnie określić, czy metoda ma zastąpić dziedziczonej metody, czy też metoda jest nową metodą, która ukrywa metodę o podobnej nazwie dziedziczonej.
W języku C#klasy pochodne mogą zawierać metody o tej samej nazwie co metody klasy bazowej.
Jeśli metoda w klasie pochodnej nie jest poprzedzona nowymi lub zastępowanymi słowami kluczowymi, kompilator wyda ostrzeżenie, a metoda będzie zachowywać się tak, jakby
new
słowo kluczowe było obecne.Jeśli metoda w klasie pochodnej jest poprzedzona
new
słowem kluczowym, metoda jest definiowana jako niezależna od metody w klasie bazowej.Jeśli metoda w klasie pochodnej jest poprzedzona
override
słowem kluczowym, obiekty klasy pochodnej wywołają tę metodę zamiast metody bazowej.Aby użyć słowa kluczowego
override
do metody w klasie pochodnej, metoda klasy bazowej musi zostać zdefiniowana jako virtual.Metodę klasy bazowej można wywołać z klasy pochodnej przy użyciu słowa kluczowego
base
.Słowa
override
kluczowe ,virtual
inew
można również stosować do właściwości, indeksatorów i zdarzeń.
Domyślnie metody języka C# nie są wirtualne. Jeśli metoda jest zadeklarowana jako wirtualna, każda klasa dziedzicząca metodę może zaimplementować własną wersję. Aby utworzyć metodę wirtualną, virtual
modyfikator jest używany w deklaracji metody klasy bazowej. Klasa pochodna może następnie zastąpić podstawową metodę wirtualną za pomocą override
słowa kluczowego lub ukryć metodę wirtualną w klasie bazowej przy użyciu słowa kluczowego new
. Jeśli nie zostanie określone ani słowo kluczowe override
, ani new
słowo kluczowe, kompilator wyświetli ostrzeżenie, a metoda w klasie pochodnej ukryje metodę w klasie bazowej.
Aby to zademonstrować w praktyce, załóżmy na chwilę, że firma A utworzyła klasę o nazwie GraphicsClass
, której używa program. Poniżej przedstawiono następujące elementy:GraphicsClass
class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
}
Firma używa tej klasy i używa jej do utworzenia własnej klasy, dodając nową metodę:
class YourDerivedGraphicsClass : GraphicsClass
{
public void DrawRectangle() { }
}
Aplikacja jest używana bez problemów, dopóki firma A nie wyda nowej wersji GraphicsClass
programu , która przypomina następujący kod:
class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
public virtual void DrawRectangle() { }
}
Nowa wersja programu GraphicsClass
zawiera teraz metodę o nazwie DrawRectangle
. Początkowo nic się nie dzieje. Nowa wersja jest nadal binarna zgodna ze starą wersją. Wszelkie wdrożone oprogramowanie będzie nadal działać, nawet jeśli nowa klasa jest zainstalowana w tych systemach komputerowych. Wszystkie istniejące wywołania metody DrawRectangle
będą nadal odwoływać się do twojej wersji w klasie pochodnej.
Jednak po ponownym skompilowaniu aplikacji przy użyciu nowej wersji GraphicsClass
programu zostanie wyświetlone ostrzeżenie kompilatora CS0108. To ostrzeżenie informuje, że musisz rozważyć, jak metoda DrawRectangle
powinna się zachowywać w kontekście aplikacji.
Jeśli chcesz, aby metoda przesłoniła nową metodę klasy bazowej, użyj słowa kluczowego override
:
class YourDerivedGraphicsClass : GraphicsClass
{
public override void DrawRectangle() { }
}
Słowo override
kluczowe zapewnia, że wszystkie obiekty pochodzące z YourDerivedGraphicsClass
klasy będą używać pochodnej DrawRectangle
wersji klasy . Obiekty pochodzące z YourDerivedGraphicsClass
mogą nadal uzyskiwać dostęp do wersji DrawRectangle
klasy bazowej przy użyciu słowa kluczowego base:
base.DrawRectangle();
Jeśli nie chcesz, aby metoda przesłoniła nową metodę klasy bazowej, należy wziąć pod uwagę następujące zagadnienia. Aby uniknąć nieporozumień między dwiema metodami, możesz zmienić nazwę metody. Może to być czasochłonne i podatne na błędy, a po prostu nie jest praktyczne w niektórych przypadkach. Jeśli jednak projekt jest stosunkowo mały, możesz użyć opcji refaktoryzacji programu Visual Studio, aby zmienić nazwę metody. Aby uzyskać więcej informacji, zobacz Refaktoryzacja klas i typów (Projektant klas).
Alternatywnie możesz zapobiec ostrzeżeniu, używając słowa kluczowego new
w definicji klasy pochodnej:
class YourDerivedGraphicsClass : GraphicsClass
{
public new void DrawRectangle() { }
}
Użycie słowa kluczowego new
informuje kompilator, że definicja ukrywa definicję zawartą w klasie bazowej. Jest to zachowanie domyślne.
Zastępowanie i wybór metody
Gdy metoda ma nazwę w klasie, kompilator języka C# wybiera najlepszą metodę do wywołania, jeśli więcej niż jedna metoda jest zgodna z wywołaniem, na przykład gdy istnieją dwie metody o tej samej nazwie i parametry zgodne z przekazanym parametrem. Następujące metody byłyby zgodne:
public class Derived : Base
{
public override void DoWork(int param) { }
public void DoWork(double param) { }
}
Po wywołaniu DoWork
w instancji Derived
, kompilator języka C# najpierw spróbuje wykonać wywołanie zgodne z wersjami DoWork
zadeklarowanymi pierwotnie w Derived
. Metody przesłonięcia nie są uznawane za zadeklarowane w klasie. Są to nowe implementacje metody zadeklarowanej w klasie bazowej. Tylko wtedy, gdy kompilator języka C# nie może dopasować wywołania metody do oryginalnej metody w systemie Derived
, spróbuje dopasować wywołanie metody do metody przesłoniętej o tej samej nazwie i zgodnych parametrach. Na przykład:
int val = 5;
Derived d = new();
d.DoWork(val); // Calls DoWork(double).
Ponieważ zmienną val
można niejawnie przekonwertować na typ double, kompilator języka C# wywołuje DoWork(double)
zamiast DoWork(int)
. Istnieją dwa sposoby, aby tego uniknąć. Najpierw należy unikać deklarowania nowych metod o tej samej nazwie co metody wirtualne. Po drugie, można poinstruować kompilator języka C#, aby wywołał metodę wirtualną, przeszukując listę metod klasy bazowej poprzez rzutowanie wystąpienia Derived
do klasy Base
. Ponieważ metoda jest wirtualna, zostanie wywołana implementacja DoWork(int)
na Derived
. Na przykład:
((Base)d).DoWork(val); // Calls DoWork(int) on Derived.
Aby uzyskać więcej przykładów elementów new
i override
, zobacz Wiedza o tym, kiedy używać przesłonięć i nowych słów kluczowych.