Außerkraftsetzen von Eigenschaften und Methoden in einer abgeleiteten Klasse
In C# können Sie das schlüsselwort override verwenden, um das Verhalten der Basisklasse in der abgeleiteten Klasse zu erweitern oder zu ändern. Mit dem schlüsselwort override können Sie Eigenschaften und Methoden außer Kraft setzen, die von der Basisklasse geerbt werden, und benutzerdefinierte Implementierungen in der abgeleiteten Klasse bereitstellen. Auf diese Weise können Sie Code wiederverwenden, der in der Basisklasse definiert ist, und das Verhalten der Basisklasse in der abgeleiteten Klasse erweitern oder ändern.
Um eine Eigenschaft oder Methode in einer abgeleiteten Klasse außer Kraft zu setzen, müssen Sie die folgenden Schritte ausführen:
- Deklarieren Sie die Member in der Basisklasse entweder als
abstractodervirtual. - Überschreiben Sie die Member in der abgeleiteten Klasse.
- Verwenden Sie optional das schlüsselwort
basefür den Zugriff auf die Basisklassenimplementierung aus dem überschriebenen Element in der abgeleiteten Klasse.
Deklarieren Sie abstrakte und virtuelle Mitglieder der Basisklasse
Bevor Sie die Member in einer abgeleiteten Klasse überschreiben können, müssen Sie die Member in der Basisklasse entweder als abstract oder virtualdeklarieren.
- Abstract: Das schlüsselwort
abstractgibt an, dass das Element keine Implementierung aufweist und in einer abgeleiteten Klasse überschrieben werden muss. - Virtual: Das schlüsselwort
virtualgibt an, dass der Member über eine Implementierung verfügt, aber in einer abgeleiteten Klasse überschrieben oder erweitert werden kann.
Im folgenden Beispiel wird veranschaulicht, wie abstrakte und virtuelle Member in einer Basisklasse deklariert werden:
public class BaseClass
{
public string Property1 { get; set; } = "Base - Property1";
public string Property2 { get; set; } = "Base - Property2";
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
public void Method2()
{
Console.WriteLine("Base - Method2");
}
}
Überschreiben von Mitgliedern in der abgeleiteten Klasse
Nachdem Sie die Member in der Basisklasse entweder als abstract oder virtual deklarieren, können Sie die Member in der abgeleiteten Klasse mithilfe des Schlüsselworts override überlagern. Das schlüsselwort override gibt an, dass der Member in der abgeleiteten Klasse den Member in der Basisklasse überschreibt.
Betrachten Sie das folgende Beispiel:
// Step 1: Create instances of the base class and the derived classes
BaseClass baseClass = new BaseClass();
DerivedClass derivedClass = new DerivedClass();
BaseClass baseClassReferencingDerivedClass = new DerivedClass();
// Step 2: Access properties and methods of the base class
Console.WriteLine($"\n{baseClass.Property1}");
Console.WriteLine($"{baseClass.Property2}");
baseClass.Method1();
baseClass.Method2();
// Step 3: Access properties and methods of the derived class
Console.WriteLine($"\n{derivedClass.Property1}");
Console.WriteLine($"{derivedClass.Property2}");
derivedClass.Method1();
derivedClass.Method2();
// Step 4: 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
Derived - Property1
Derived - Property2
Derived - Method1
Derived - Method2
Derived - Property1
Base - Property2
Derived - Method1
Base - Method2
*/
public class BaseClass
{
public virtual string Property1 { get; set; } = "Base - Property1";
public virtual string Property2 { get; set; } = "Base - Property2";
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
public void Method2()
{
Console.WriteLine("Base - Method2");
}
}
public class DerivedClass : BaseClass
{
public override string Property1 { get; set; } = "Derived - Property1";
public new string Property2 { get; set; } = "Derived - Property2";
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
}
Dieser Code veranschaulicht, wie Eigenschaften und Methoden in einer abgeleiteten Klasse mithilfe der schlüsselwörter override und new geändert und ausgeblendet werden. Der Code definiert eine Basisklasse (BaseClass) und eine abgeleitete Klasse (DerivedClass), die von der Basisklasse erbt. Die Basisklasse verfügt über zwei Eigenschaften (Property1 und Property2) und zwei Methoden (Method1 und Method2). Die abgeleitete Klasse setzt Property1 und Method1 außer Kraft und blendet Property2 und Method2 mithilfe des schlüsselworts new aus.
Hier ist eine Aufschlüsselung des Codes:
In Schritt 1 erstellt der Code eine Instanz der Basisklasse (
baseClass), eine Instanz der abgeleiteten Klasse (derivedClass) und eine Instanz der abgeleiteten Klasse, auf die durch eine Basisklassenvariable (baseClassReferencingDerivedClass) verwiesen wird. DiebaseClassReferencingDerivedClassInstanz veranschaulicht Polymorphismus, wobei ein Basisklassenverweis auf ein abgeleitetes Klassenobjekt verweist.In Schritt 2 greift der Code auf die Eigenschaften und Methoden der Basisklasseninstanz zu und druckt sie. Da
baseClasseine Instanz vonBaseClassist, werden die inBaseClassdefinierten Eigenschaften und Methoden verwendet. Die Ausgabe zeigt die Werte und Verhaltensweisen wie in der Basisklasse definiert an.In Schritt 3 greift der Code auf die Eigenschaften und Methoden der abgeleiteten Klasseninstanz zu und druckt sie. Da
derivedClasseine Instanz vonDerivedClassist, werden die überschriebenen Eigenschaften und Methoden verwendet, die inDerivedClassdefiniert sind. Die Ausgabe spiegelt die Werte und Verhaltensweisen wider, die in der abgeleiteten Klasse definiert sind.In Schritt 4 greift der Code auf die Eigenschaften und Methoden der abgeleiteten Klasseninstanz zu, auf die durch eine Basisklassenvariable verwiesen wird. Für Eigenschaften und Methoden, die überschrieben werden (
Property1undMethod1), wird die abgeleitete Klassenimplementierung verwendet. Bei Eigenschaften und Methoden, die ausgeblendet sind (Property2undMethod2), wird jedoch die Basisklassenimplementierung verwendet. Dies veranschaulicht den Unterschied zwischen Methodenüberschreibung (unter Verwendung vonoverride) und dem Ausblenden von Methoden (mitnew).
Definieren einer abstrakten Basisklasse
Wenn Sie eine Basisklasse als abstractdefinieren, geben Sie an, dass die Klasse unvollständig ist und von abgeleiteten Klassen implementiert werden muss. Abstrakte Klassen können abstrakte Eigenschaften und Methoden enthalten, die von abgeleiteten Klassen implementiert werden müssen. Abstrakte Basisklassen können nicht direkt instanziiert werden, daher werden sie als Vorlage für abgeleitete Klassen verwendet, um die abstrakten Elemente zu implementieren.
Betrachten Sie das folgende Beispiel:
// create instances of the base class and the derived classes
// Note: We can't create an instance of an abstract class
// BaseClass baseClass = new BaseClass(); // This line would cause a compile-time error
DerivedClass derivedClass = new DerivedClass();
BaseClass baseClassReferencingDerivedClass = new DerivedClass();
// 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:
Derived - Property1
Derived - Property2
Derived - Method1
Derived - Method2
Derived - Property1
Base - Property2
Derived - Method1
Base - Method2
*/
public abstract class BaseClass
{
public abstract string Property1 { get; set; }
public virtual string Property2 { get; set; } = "Base - Property2";
public abstract void Method1();
public void Method2()
{
Console.WriteLine("Base - Method2");
}
}
public class DerivedClass : BaseClass
{
public override string Property1 { get; set; } = "Derived - Property1";
public new string Property2 { get; set; } = "Derived - Property2";
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
}
Beachten Sie, dass die Basisklasse nicht direkt instanziiert werden kann, wenn die Basisklasse mithilfe des schlüsselworts abstract deklariert wird. Stattdessen müssen Sie Instanzen der abgeleiteten Klassen erstellen, die die abstrakten Member implementieren. Die abgeleitete Klasse muss Implementierungen für die abstrakten Elemente bereitstellen, die in der Basisklasse definiert sind. Elemente, die nicht abstrakt sind, können in der abgeleiteten Klasse überschrieben oder ausgeblendet werden.
Implizit geerbte Mitglieder der Object-Klasse außer Kraft setzen
Alle Klassen in C# erben implizit von der Object Klasse. Die Object Klasse definiert mehrere Member, die von allen Klassen geerbt werden, z. B. ToString, Equalsund GetHashCode. Sie können diese Mitglieder in Ihren Klassen überschreiben, um benutzerdefinierte Implementierungen bereitzustellen.
Betrachten Sie das folgende Beispiel:
// create instances of the derived classes
DerivedClass1 derivedClass1 = new DerivedClass1();
DerivedClass2 derivedClass2a = new DerivedClass2 { Property1 = "Value1", Property2 = "Value2" };
DerivedClass2 derivedClass2b = new DerivedClass2 { Property1 = "Value1", Property2 = "Value2" };
DerivedClass2 derivedClass2c = new DerivedClass2 { Property1 = "Value3", Property2 = "Value4" };
// demonstrate Object class methods for DerivedClass1
Console.WriteLine("\nDemonstrating Object class methods for DerivedClass1:");
Console.WriteLine($"ToString: {derivedClass1.ToString()}");
Console.WriteLine($"Equals: {derivedClass1.Equals(new DerivedClass1())}");
Console.WriteLine($"GetHashCode: {derivedClass1.GetHashCode()}");
// demonstrate overridden Object class methods for DerivedClass2
Console.WriteLine("\nDemonstrating overridden Object class methods for DerivedClass2:");
Console.WriteLine($"ToString: {derivedClass2a.ToString()}");
Console.WriteLine($"Equals (derivedClass2a vs derivedClass2b): {derivedClass2a.Equals(derivedClass2b)}"); // should return true
Console.WriteLine($"Equals (derivedClass2a vs derivedClass2c): {derivedClass2a.Equals(derivedClass2c)}"); // should return false
Console.WriteLine($"GetHashCode (derivedClass2a): {derivedClass2a.GetHashCode()}");
Console.WriteLine($"GetHashCode (derivedClass2b): {derivedClass2b.GetHashCode()}");
Console.WriteLine($"GetHashCode (derivedClass2c): {derivedClass2c.GetHashCode()}");
/*Output:
Demonstrating Object class methods for DerivedClass1:
ToString: DerivedClass1
Equals: False
GetHashCode: [HashCode]
Demonstrating overridden Object class methods for DerivedClass2:
ToString: DerivedClass2: Property1 = Value1, Property2 = Value2
Equals (derivedClass2a vs derivedClass2b): True
Equals (derivedClass2a vs derivedClass2c): False
GetHashCode (derivedClass2a): [HashCode]
GetHashCode (derivedClass2b): [HashCode]
GetHashCode (derivedClass2c): [HashCode]
*/
public abstract class BaseClass
{
public abstract string Property1 { get; set; }
public virtual string Property2 { get; set; } = "Base - Property2";
public abstract void Method1();
public void Method2()
{
Console.WriteLine("Base - Method2");
}
}
public class DerivedClass1 : BaseClass
{
public override string Property1 { get; set; } = "Derived1 - Property1";
public new string Property2 { get; set; } = "Derived1 - Property2";
public override void Method1()
{
Console.WriteLine("Derived1 - Method1");
}
public new void Method2()
{
Console.WriteLine("Derived1 - Method2");
}
}
public class DerivedClass2 : BaseClass
{
public override string Property1 { get; set; } = "Derived2 - Property1";
public new string Property2 { get; set; } = "Derived2 - Property2";
public override void Method1()
{
Console.WriteLine("Derived2 - Method1");
}
public new void Method2()
{
Console.WriteLine("Derived2 - Method2");
}
// Override ToString method
public override string ToString()
{
return $"DerivedClass2: Property1 = {Property1}, Property2 = {Property2}";
}
// Override Equals method
public override bool Equals(object obj)
{
if (obj is DerivedClass2 other)
{
return Property1 == other.Property1 && Property2 == other.Property2;
}
return false;
}
// Override GetHashCode method
public override int GetHashCode()
{
return HashCode.Combine(Property1, Property2);
}
}
In diesem Beispiel erben die klassen DerivedClass1 und DerivedClass2 von der BaseClass klasse. Die DerivedClass2 Klasse überschreibt die methoden ToString, Equalsund GetHashCode, die von der Object Klasse geerbt wurden. Die ToString-Methode gibt eine Zeichenfolgendarstellung des Objekts zurück, die Equals-Methode vergleicht zwei Objekte für die Gleichheit, und die GetHashCode-Methode gibt einen Hashcode für das Objekt zurück. Die DerivedClass2-Klasse stellt benutzerdefinierte Implementierungen für diese Methoden bereit, um die Eigenschaften des Objekts anzuzeigen und Objekte basierend auf ihren Eigenschaften zu vergleichen.
Zusammenfassung
Durch das Überschreiben von Eigenschaften und Methoden in einer abgeleiteten Klasse können Sie das Verhalten der Basisklasse erweitern oder ändern. Mithilfe des Schlüsselworts override können Sie benutzerdefinierte Implementierungen für Eigenschaften und Methoden bereitstellen, die von der Basisklasse geerbt werden. Auf diese Weise können Sie Code wiederverwenden, der in der Basisklasse definiert ist, und das Verhalten der Basisklasse in der abgeleiteten Klasse erweitern oder ändern. Sie können auch das schlüsselwort new verwenden, um Eigenschaften und Methoden in der Basisklasse auszublenden und neue Implementierungen in der abgeleiteten Klasse bereitzustellen.