Przechowywanie wersji przesłonięć i nowych słów kluczowych (Przewodnik programowania w języku C#)

Język C# został zaprojektowany tak, aby przechowywanie wersji między klasami podstawowymi i pochodnymi w różnych bibliotekach może ewoluować i zachować zgodność z poprzednimi wersjami. 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 zastosować override słowo kluczowe do metody w klasie pochodnej, należy zdefiniować metodę klasy bazowej.

  • Metodę klasy bazowej można wywołać z klasy pochodnej przy użyciu słowa kluczowego base .

  • Słowa overridekluczowe , virtuali new 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 ani override słowo kluczowe, ani słowo kluczowe nie new zostanie określone, 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 GraphicsClassprogramu , 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 używanej wersji w klasie pochodnej.

Jednak po ponownym skompilowaniu aplikacji przy użyciu nowej wersji GraphicsClassprogramu zostanie wyświetlone ostrzeżenie kompilatora CS0108. To ostrzeżenie informuje, że musisz wziąć pod uwagę sposób DrawRectangle zachowania metody w 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 DrawRectanglewersji klasy . Obiekty pochodzące z YourDerivedGraphicsClass programu mogą nadal uzyskiwać dostęp do wersji DrawRectangle klasy bazowej przy użyciu podstawowego słowa kluczowego:

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 (klasa Projektant).

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. To jest 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 DoWork wywołaniu w wystąpieniu Derivedprogramu kompilator języka C# najpierw spróbuje wykonać wywołanie zgodne z wersjami zadeklarowanymi DoWork pierwotnie na .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 Derived();
d.DoWork(val);  // Calls DoWork(double).

Ponieważ zmienną val można przekonwertować na dwukrotnie niejawnie, 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ą, wyszukując listę metod klasy bazowej przez rzutowanie wystąpienia Derived do Baseklasy . Ponieważ metoda jest wirtualna, zostanie wywołana implementacja DoWork(int) polecenia on Derived . Na przykład:

((Base)d).DoWork(val);  // Calls DoWork(int) on Derived.

Aby uzyskać więcej przykładów elementów new i , zobacz Wiedza o tym, kiedy używać przesłonięć i nowych słów kluczowychoverride.

Zobacz też