Erweitern einer abgeleiteten Klasse mit neuen Membern

Abgeschlossen

Eine abgeleitete Klasse wird verwendet, um die Basisklasse zu erweitern oder zu ändern, von der sie erbt.

Wenn Sie eine abgeleitete Klasse erstellen, haben Sie mehrere Optionen zum Erweitern der Basisklasse:

  • Sie können neue Eigenschaften und Methoden in der abgeleiteten Klasse definieren, die in der Basisklasse nicht vorhanden sind. Mit dieser Option können Sie das Verhalten der Basisklasse erweitern, indem Sie mehr Funktionen in der abgeleiteten Klasse bereitstellen.
  • Sie können Eigenschaften und Methoden in der abgeleiteten Klasse definieren, die denselben Namen wie Eigenschaften und Methoden in der Basisklasse haben. In solchen Fällen können Sie das schlüsselwort new verwenden, um die Basisklassenmember auszublenden.
  • Sie können Eigenschaften und Methoden in der abgeleiteten Klasse definieren, die Eigenschaften und Methoden in der Basisklasse überschreiben. In solchen Fällen können Sie das schlüsselwort override verwenden, um das Verhalten der Basisklassenmember zu erweitern oder zu ändern.

Die Verwendung des schlüsselworts new kann auch verwendet werden, um versehentliche Außerkraftsetzungen von Basisklassenmembern zu vermeiden. Durch die Verwendung des schlüsselworts new wird sichergestellt, dass das abgeleitete Klassenmember als separate Entität behandelt wird.

Hinzufügen neuer Member zu einer abgeleiteten Klasse, die in der Basisklasse nicht vorhanden ist

Wenn Sie eine abgeleitete Klasse erstellen, können Sie neue Eigenschaften und Methoden hinzufügen, die das Verhalten und die Funktionalität der Basisklasse erweitern. Sie müssen jedoch entweder Namenskonflikte zwischen der Basisklasse und der abgeleiteten Klasse verwalten oder vermeiden.

Betrachten Sie das folgende Beispiel:


// create instances of the base class and the derived classes
BaseClass baseClass = new BaseClass();
DerivedClass derivedClass = new DerivedClass();
BaseClass baseClassReferencingDerivedClass = new DerivedClass();

// access properties and methods of the base class
Console.WriteLine($"\n{baseClass.Property1}");
baseClass.Method1();

// access properties and methods of the derived class
Console.WriteLine($"\n{derivedClass.Property1}");
derivedClass.Method1();
Console.WriteLine($"{derivedClass.Property2}");
derivedClass.Method2();

// access properties and methods of the base class that references the derived class
Console.WriteLine($"\n{baseClassReferencingDerivedClass.Property1}");
baseClassReferencingDerivedClass.Method1();
//baseClassReferencingDerivedClass.Method2(); //Generates error: 'BaseClass' doesn't contain a definition for 'Method2' ...

/*Output:
Base - Property1
Base - Method1

Base - Property1
Base - Method1
Derived - Property2
Derived - Method2

Base - Property1
Base - Method1
*/

public class BaseClass
{
    public string Property1 { get; set; } = "Base - Property1";

    public void Method1()
    {
        Console.WriteLine("Base - Method1");
    }
}

public class DerivedClass : BaseClass
{
    public string Property2 { get; set; } = "Derived - Property2";

    public void Method2()
    {
        Console.WriteLine("Derived - Method2");
    }
}

Dieses Codebeispiel enthält Anweisungen der obersten Ebene und zwei Klassen: BaseClass und DerivedClass. Die BaseClass Klasse definiert eine Eigenschaft mit dem Namen Property1 und eine Methode mit dem Namen Method1. Die abgeleitete Klasse DerivedClass erweitert die Basisklasse mit einer neuen Eigenschaft namens Property2 und einer neuen Methode mit dem Namen Method2. Es gibt keine Namenskonflikte zwischen der Basis und abgeleiteten Klassen, sodass Sie auf die neuen und geerbten Member aus einer Instanz der abgeleiteten Klasse zugreifen können.

Der Code erstellt eine Instanz von BaseClass benannten baseClass und eine Instanz von DerivedClass benannten derivedClass. Der Code erstellt außerdem eine Instanz von BaseClass namens baseClassReferencingDerivedClass, die auf eine Instanz von DerivedClassverweist. Der Code führt dann die folgenden Schritte aus:

  • Es verwendet baseClass, um den Wert von Property1 anzuzeigen und Method1aufzurufen.
  • Es verwendet derivedClass zum Anzeigen des Werts von Property1, aufrufen Method1, Anzeigen des Werts von Property2und aufrufen Method2.
  • Es verwendet baseClassReferencingDerivedClass, um Method1 aufzurufen und den Wert von Property1anzuzeigen.

Beachten Sie, dass die Variable baseClassReferencingDerivedClass als Typ BaseClassdeklariert wird, aber eine Instanz vom Typ DerivedClasszugewiesen wurde. Die Verwendung dieser Deklarationssyntax bedeutet, dass das baseClassReferencingDerivedClass-Objekt zwar einen Verweis auf die abgeleitete Klasse enthält, aber dennoch wie eine Instanz der Basisklasse behandelt wird. Ein Versuch, Method2 aufzurufen, würde zu einem Kompilierungsfehler führen, da die Basisklasse keine Methode mit dem Namen Method2hat. Wenn eine App ein Objekt als Basisklassentyp instanziiert und das Objekt dann einer abgeleiteten Klasseninstanz zuweist, ist es bereit, Polymorphismus zu implementieren. Obwohl Klassenvererbung häufig zur Unterstützung von Polymorphismus verwendet wird, sind Vererbung und Polymorphismus unterschiedliche Themen. Polymorphismus wird in einem separaten Modul untersucht.

Wenn Sie den Code ausführen, wird die folgende Ausgabe angezeigt:


Base - Method1

Base - Property1

Base - Method1

Base - Property1

Derived - Method2

Derived - Property2

Base - Method1

Base - Property1

Die Basisklassenobjekte, baseClass und baseClassReferencingDerivedClass, können nur auf die in der Basisklasse definierten Eigenschaften und Methoden zugreifen. Das abgeleitete Klassenobjekt derivedClasskann sowohl in der Basisklasse als auch in der abgeleiteten Klasse auf Eigenschaften und Methoden zugreifen.

Hinzufügen neuer Member zu einer abgeleiteten Klasse, die in der Basisklasse vorhanden ist

Wenn Sie einer abgeleiteten Klasse neue Member hinzufügen, müssen Sie sich der Benennungskonflikte zwischen der Basisklasse und der abgeleiteten Klasse bewusst sein. Ein Namenskonflikt tritt auf, wenn eine abgeleitete Klasse ein Element mit demselben Namen wie ein Element in der Basisklasse definiert.

Betrachten Sie das folgende Codebeispiel, das einen Namenskonflikt zwischen der Basisklasse und der abgeleiteten Klasse enthält:


// create instances of the base class and the derived classes
BaseClass baseClass = new BaseClass();
DerivedClass derivedClass = new DerivedClass();
BaseClass baseClassReferencingDerivedClass = new DerivedClass();

// access properties and methods of the base class
Console.WriteLine($"\n{baseClass.Property1}");
Console.WriteLine($"{baseClass.Property2}");
baseClass.Method1();
baseClass.Method2();

// access properties and methods of the derived class
Console.WriteLine($"\n{derivedClass.Property1}");
Console.WriteLine($"{derivedClass.Property2}");
derivedClass.Method1();
derivedClass.Method2();

// access properties and methods of the base class that references the derived class
Console.WriteLine($"\n{baseClassReferencingDerivedClass.Property1}");
Console.WriteLine($"{baseClassReferencingDerivedClass.Property2}");
baseClassReferencingDerivedClass.Method1();
baseClassReferencingDerivedClass.Method2();

/*Output:
Base - Property1
Base - Property2
Base - Method1
Base - Method2

Base - Property1
Derived - Property2
Base - Method1
Derived - Method2

Base - Property1
Base - Property2
Base - Method1
Base - Method2
*/

public class BaseClass
{
    public string Property1 { get; set; } = "Base - Property1";
    public string Property2 { get; set; } = "Base - Property2";

    public void Method1()
    {
        Console.WriteLine("Base - Method1");
    }

    public void Method2()
    {
        Console.WriteLine("Base - Method2");
    }
}

public class DerivedClass : BaseClass
{
    public string Property2 { get; set; } = "Derived - Property2";

    public void Method2()
    {
        Console.WriteLine("Derived - Method2");
    }
}

Beachten Sie, dass Property2 und Method2 in der abgeleiteten Klasse den gleichen Namen wie Property2 und Method2 in der Basisklasse haben. Das Duplizieren von Membern erstellt einen Namenskonflikt zwischen der Basis und abgeleiteten Klassen. Beim Erstellen der Lösung wird eine Warnung generiert, die besagt, dass Member der abgeleiteten Klasse Member ausblenden, die von der Basisklasse geerbt werden.


warning CS0108: 'DerivedClass.Property2' hides inherited member 'BaseClass.Property2'. Use the new keyword if hiding was intended.

warning CS0108: 'DerivedClass.Method2()' hides inherited member 'BaseClass.Method2()'. Use the new keyword if hiding was intended.

Wenn Sie den Code ausführen, wird die folgende Ausgabe angezeigt:


Base - Property1
Base - Property2
Base - Method1
Base - Method2

Base - Property1
Derived - Property2
Base - Method1
Derived - Method2

Base - Property1
Base - Property2
Base - Method1
Base - Method2

Die Ausgabe zeigt, dass die Property2-Eigenschaft und die Method2 Methode der abgeleiteten Klasse aufgerufen werden, wenn das als abgeleitete Klasse deklarierte Objekt verwendet wird. Die Property2-Eigenschaft und die Method2 Methode der Basisklasse werden aufgerufen, wenn das als Basisklasse deklarierte Objekt verwendet wird.

Wenn sie einen Namenskonflikt zwischen der Basisklasse und der abgeleiteten Klasse haben, können Sie das schlüsselwort new verwenden, um das Basisklassenmember absichtlich auszublenden. Mit dem schlüsselwort new können Sie ein neues Element in der abgeleiteten Klasse definieren, das denselben Namen wie ein Element in der Basisklasse hat.

Anmerkung

Die Verwendung des schlüsselworts override wird in der nächsten Einheit erläutert.

Verwenden des schlüsselworts new, um Namenskonflikte zu vermeiden

Wenn sie einen Namenskonflikt zwischen der Basisklasse und der abgeleiteten Klasse haben, können Sie das schlüsselwort new verwenden, um das Basisklassenmember absichtlich auszublenden. Mit dieser Syntax können Sie ein neues Element in der abgeleiteten Klasse definieren, das denselben Namen wie ein Element in der Basisklasse hat. Die Verwendung des schlüsselworts new auf diese Weise ändert nicht das Standardverhalten des Compilers zum Auflösen von Namenskonflikten, unterdrückt jedoch die Warnung, die beim Erstellen der Lösung auftritt, und es wird die Absicht, das Basisklassenmember explizit auszublenden.

Der folgende Code verwendet das schlüsselwort new in der abgeleiteten Klasse, um die Property2-Eigenschaft und die in der Basisklasse definierte Method2 Methode auszublenden:


// create instances of the base class and the derived classes
BaseClass baseClass = new BaseClass();
DerivedClass derivedClass = new DerivedClass();
BaseClass baseClassReferencingDerivedClass = new DerivedClass();

// access properties and methods of the base class
Console.WriteLine($"\n{baseClass.Property1}");
Console.WriteLine($"{baseClass.Property2}");
baseClass.Method1();
baseClass.Method2();

// access properties and methods of the derived class
Console.WriteLine($"\n{derivedClass.Property1}");
Console.WriteLine($"{derivedClass.Property2}");
derivedClass.Method1();
derivedClass.Method2();

// access properties and methods of the base class that references the derived class
Console.WriteLine($"\n{baseClassReferencingDerivedClass.Property1}");
Console.WriteLine($"{baseClassReferencingDerivedClass.Property2}");
baseClassReferencingDerivedClass.Method1();
baseClassReferencingDerivedClass.Method2();

/*Output:
Base - Property1
Base - Property2
Base - Method1
Base - Method2

Base - Property1
Derived - Property2
Base - Method1
Derived - Method2

Base - Property1
Base - Property2
Base - Method1
Base - Method2
*/

public class BaseClass
{
    public string Property1 { get; set; } = "Base - Property1";
    public string Property2 { get; set; } = "Base - Property2";

    public void Method1()
    {
        Console.WriteLine("Base - Method1");
    }

    public void Method2()
    {
        Console.WriteLine("Base - Method2");
    }
}

public class DerivedClass : BaseClass
{
    public new string Property2 { get; set; } = "Derived - Property2";

    public new void Method2()
    {
        Console.WriteLine("Derived - Method2");
    }
}

Wenn Sie den Code ausführen, entspricht die Ausgabe dem im vorherigen Beispiel. Das schlüsselwort new wird in der abgeleiteten Klasse verwendet, um die Property2-Eigenschaft und die in der Basisklasse definierte Method2 Methode auszublenden. Die Property2-Eigenschaft und die Method2-Methode der abgeleiteten Klasse werden aufgerufen, wenn das als abgeleitete Klasse deklarierte Objekt verwendet wird. Die Property2-Eigenschaft und die Method2 Methode der Basisklasse werden aufgerufen, wenn das als Basisklasse deklarierte Objekt verwendet wird.

Allgemeine Anleitungen zur Verwendung des schlüsselworts new

Das schlüsselwort new kann verwendet werden, um ein Element der Basisklasse absichtlich auszublenden. Dieses Verhalten ist nützlich, wenn die abgeleitete Klasse eine andere Implementierung oder Funktionalität bereitstellen muss, die nicht mit dem Basisklassenmember kompatibel ist. Das schlüsselwort new kann auch verwendet werden, um sicherzustellen, dass die Absicht, das Basisklassenelement auszublenden, klar ist. Ohne das schlüsselwort new kann es unklar sein, ob das abgeleitete Klassenmember das Basisklassenelement überschreiben oder ausblenden soll.

Verwenden Sie beim Anwenden des Schlüsselworts new die folgenden Richtlinien:

  • Verwenden Sie das schlüsselwort new, wenn Sie ein Element der Basisklasse absichtlich ausblenden möchten. Durch das Ausblenden des Basisklassenmember wird sichergestellt, dass das abgeleitete Klassenmember als separate Entität behandelt wird.
  • Verwenden Sie das schlüsselwort new, wenn Sie die versehentliche Außerkraftsetzung von Basisklassenmembern vermeiden möchten. Absichtlich das Schlüsselwort new zu verlassen, kann ein anderer Entwickler glauben, dass das abgeleitete Klassenelement überschrieben werden sollte.
  • Vermeiden Sie die Verwendung des schlüsselworts new, wenn Sie das Verhalten eines Basisklassenelements erweitern oder ändern möchten. In solchen Fällen sollten Sie stattdessen das schlüsselwort override verwenden.
  • Vermeiden Sie die Verwendung des schlüsselworts new, wenn dies zu Verwirrung oder Mehrdeutigkeit im Code führt. Stellen Sie sicher, dass der Zweck, das Element der Basisklasse auszublenden, klar und gerechtfertigt ist.

Zusammenfassung

Eine abgeleitete Klasse kann das Verhalten einer Basisklasse erweitern, indem neue Eigenschaften und Methoden hinzugefügt werden. Sie können das schlüsselwort new verwenden, um Basisklassenmember absichtlich auszublenden oder versehentliche Außerkraftsetzungen von Basisklassenmembern zu vermeiden. Mit dem schlüsselwort new können Sie neue Member in einer abgeleiteten Klasse definieren, die denselben Namen wie Member in der Basisklasse haben.