Konfigurieren von Basis- und abgeleiteten Klassen
Die Begriffe Basisklasse und abgeleiteten Klassen werden verwendet, um die Beziehung zwischen Klassen in einer Vererbungshierarchie zu beschreiben. Eine Basisklasse wird verwendet, um einen allgemeinen Satz von Attributen und Verhaltensweisen zu definieren, die andere Klassen erben. Eine abgeleitete Klasse wird verwendet, um einen speziellen Satz von Attributen und Verhaltensweisen zu definieren, die die Basisklasse erweitern oder ändern.
Untersuchen der transitiven Natur der Vererbung
In C# kann eine Klasse nur von einer Basisklasse erben. Diese Einschränkung wird als einzelne Vererbung bezeichnet. Die einfache Vererbung ermöglicht es einer abgeleiteten Klasse, auf die Eigenschaften und Methoden einer einzelnen Basisklasse zuzugreifen und eine klare und einfache Hierarchie zu fördern. Das Konzept mehrerer Vererbung wird in C# nicht unterstützt. Diese Einschränkung vermeidet die Komplexitäten und Mehrdeutigkeiten, die beim Erben von mehreren Basisklassen auftreten können. Stattdessen verwendet C# Schnittstellen, um ähnliche Funktionen zu erzielen.
Obwohl eine Klasse nur von einer Basisklasse erben kann, ist die Vererbung transitiv. Dies bedeutet: Wenn eine Klasse C von Klasse B erbt und Klasse B von Klasse A erbt, erbt Klasse C die in Klasse B und Klasse A deklarierten Member. Diese Eigenschaft ermöglicht eine tiefere Hierarchie und eine weitere Wiederverwendung von Code.
Betrachten Sie beispielsweise ein Fahrzeugmanagementsystem, bei dem Sie über eine Basisklasse Vehicleverfügen, eine abgeleitete Klasse Car, die von Vehicleerbt, und eine andere abgeleitete Klasse ElectricCar, die von Carerbt. In dieser Hierarchie erbt ElectricCar Elemente sowohl von Car als auch von Vehicle, wobei die transitive Art der Vererbung veranschaulicht wird.
public class Vehicle
{
public string Make { get; set; }
public string Model { get; set; }
public void StartEngine()
{
Console.WriteLine("Engine started.");
}
public void StopEngine()
{
Console.WriteLine("Engine stopped.");
}
}
public class Car : Vehicle
{
public int NumberOfDoors { get; set; }
public void OpenTrunk()
{
Console.WriteLine("Trunk opened.");
}
public void HonkHorn()
{
Console.WriteLine("Horn honked.");
}
public void LockDoors()
{
Console.WriteLine("Doors locked.");
}
}
public class ElectricCar : Car
{
public int BatteryCapacity { get; set; }
public void ChargeBattery()
{
Console.WriteLine("Battery charging.");
}
public void DisplayBatteryStatus()
{
Console.WriteLine("Battery status displayed.");
}
}
public class CombustionEngineCar : Car
{
public int FuelCapacity { get; set; }
public void Refuel()
{
Console.WriteLine("Car refueled.");
}
public void CheckOilLevel()
{
Console.WriteLine("Oil level checked.");
}
}
In diesem Beispiel wird ein einfaches Fahrzeugmanagementsystem mit den folgenden Klassen veranschaulicht:
VehicleKlasse: Die BasisklasseVehicleenthält allgemeine Eigenschaften und Methoden für alle Fahrzeuge, z. B. Make, Model, StartEngine und StopEngine.CarKlasse: DieCarKlasse erbt vonVehicleund fügt spezifische Eigenschaften und Methoden für Autos hinzu, z. B.NumberOfDoors,OpenTrunk,HonkHornundLockDoors.ElectricCarKlasse: DieElectricCarKlasse erbt vonCarund fügt Eigenschaften und Methoden speziell für Elektroautos hinzu, z. B.BatteryCapacity,ChargeBatteryundDisplayBatteryStatus.CombustionEngineCarKlasse: DieCombustionEngineCarKlasse erbt auch vonCarund fügt Eigenschaften und Methoden speziell für Verbrennungsmotorenautos hinzu, z. B.FuelCapacity,RefuelundCheckOilLevel.
In diesem Beispiel erbt die Car-Klasse Member von der Vehicle Klasse, und die ElectricCar und CombustionEngineCar erben Member von der Car Klasse. Diese Hierarchie veranschaulicht die transitive Art der Vererbung, wobei ElectricCar und CombustionEngineCar Member sowohl von Car als auch von Vehicleerben.
Überprüfung der Vererbung und Sichtbarkeit von Membervariablen
Wenn eine Klasse von einer Basisklasse erbt, gelten die folgenden Regeln:
- Statische Konstruktoren und Instanzkonstruktoren werden nicht geerbt.
- Alle anderen Mitglieder der Basisklasse werden geerbt, aber Zugriffsmodifizierer beeinflussen ihre Sichtbarkeit in der abgeleiteten Klasse. Zu den Zugriffsmodifizierern gehören:
public,protected,internalundprivate.
Öffentliche Mitglieder
Öffentliche Member sind über jeden Code zugänglich, der Zugriff auf die Klasse hat. Abgeleitete Klassen erben öffentliche Member und sind außerhalb der Klassenhierarchie zugänglich.
public class BaseClass
{
public int publicField;
public void PublicMethod() { }
}
public class DerivedClass : BaseClass
{
public void AccessPublicMember()
{
publicField = 10;
PublicMethod();
}
}
In diesem Beispiel erbt die DerivedClass die publicField und PublicMethod Mitglieder von der BaseClass. Die AccessPublicMember-Methode im DerivedClass kann auf diese Mitglieder zugreifen. Auf öffentliche Member kann auch über Code zugegriffen werden, der sich außerhalb der Klassenhierarchie befindet.
Geschützte Mitglieder
Geschützte Member sind innerhalb der Klasse, in der sie deklariert sind, und innerhalb abgeleiteter Klassen zugänglich. Auf sie kann nicht von außerhalb der Klassenhierarchie zugegriffen werden.
public class BaseClass
{
protected int protectedField;
protected void ProtectedMethod() { }
}
public class DerivedClass : BaseClass
{
public void AccessProtectedMember()
{
protectedField = 10;
ProtectedMethod();
}
}
In diesem Beispiel erbt die DerivedClass die protectedField und ProtectedMethod Mitglieder von der BaseClass. Die AccessProtectedMember-Methode im DerivedClass kann auf diese Mitglieder zugreifen. Wenn Sie jedoch versuchen, auf geschützte Member außerhalb der Klassenhierarchie zuzugreifen, wird ein Kompilierungszeitfehler generiert.
Interne Mitglieder
Auf interne Member kann innerhalb derselben Assembly zugegriffen werden. Von außerhalb der Assembly kann nicht auf sie zugegriffen werden, auch wenn die Klasse geerbt wird.
public class BaseClass
{
internal int internalField;
internal void InternalMethod() { }
}
public class DerivedClass : BaseClass
{
public void AccessInternalMember()
{
internalField = 10;
InternalMethod();
}
}
In diesem Beispiel erbt die DerivedClass die internalField und InternalMethod Mitglieder von der BaseClass. Die AccessInternalMember-Methode in DerivedClass kann auf diese Member zugreifen, da sie sich in derselben Assembly befinden. Wenn Sie jedoch versuchen, auf interne Member von außerhalb der Assembly zuzugreifen, wird ein Kompilierungszeitfehler generiert.
Private Mitglieder
Auf private Mitglieder kann nur in der Klasse zugegriffen werden, in der sie deklariert werden. Abgeleitete Klassen erben private Member nicht, sodass sie nicht direkt in der abgeleiteten Klasse zugänglich sind.
public class BaseClass
{
private int privateField;
private void PrivateMethod() { }
}
public class DerivedClass : BaseClass
{
public void AccessPrivateMember()
{
// Can't access privateField or PrivateMethod
}
}
In diesem Beispiel erbt die DerivedClass von der BaseClass, kann jedoch nicht auf die privateField oder PrivateMethod Mitglieder zugreifen, da sie privat sind.
Untersuchen der Verwendung abstrakter, virtueller und versiegelter Schlüsselwörter in der Basisklasse
Basis- und abgeleitete Klassen verwenden die abstract, virtualund sealed Schlüsselwörter, um das Verhalten der geerbten Member zu steuern. Mit diesen Schlüsselwörtern können Sie die Kontrollebene festlegen, die abgeleitete Klassen über die Member der Basisklasse haben.
Untersuchen Sie die Verwendung des Schlüsselworts abstract
Das schlüsselwort abstract in C# wird verwendet, um Klassen und Klassenmmber zu definieren, die unvollständig sind und in abgeleiteten Klassen implementiert werden müssen. Eine abstrakte Klasse kann nicht direkt instanziiert werden und soll eine Basisklasse für andere Klassen sein. Abstrakte Methoden und Eigenschaften werden ohne Implementierung deklariert und müssen in nichtabstrakten abgeleiteten Klassen überschrieben werden.
Zum Beispiel:
public abstract class Shape
{
public abstract int GetArea();
}
public class Square : Shape
{
private int _side;
public Square(int side)
{
_side = side;
}
public override int GetArea()
{
return _side * _side;
}
}
class Program
{
static void Main()
{
Square square = new Square(5);
Console.WriteLine($"Area of the square = {square.GetArea()}");
}
}
In diesem Beispiel ist die Shape Klasse abstrakt und enthält eine abstrakte Methode GetArea. Die Square-Klasse erbt von Shape und stellt eine Implementierung für die GetArea-Methode bereit. Die Square Klasse kann instanziiert werden, und die GetArea-Methode gibt den Bereich des Quadrats zurück.
Die folgenden Regeln beschreiben, wie sich das schlüsselwort abstract auf die Vererbung auswirkt:
- Abstrakte Klassen: Eine abstrakte Klasse kann nicht direkt instanziiert werden. Die abstrakte Klasse ist eine Basisklasse für abgeleitete Klassen, und die abgeleiteten Klassen müssen Implementierungen für alle abstrakten Member der abstrakten Klasse bereitstellen.
- Abstrakte Methoden: Abstrakte Methoden werden ohne Implementierung in der abstrakten Klasse deklariert. Abgeleitete Klassen müssen diese Methoden überschreiben und die Implementierung bereitstellen.
- Abstrakte Eigenschaften: Ähnlich wie abstrakte Methoden werden abstrakte Eigenschaften ohne Implementierung deklariert und müssen in abgeleiteten Klassen überschrieben werden.
Das schlüsselwort abstract in C# ist ein leistungsfähiges Tool zum Definieren unvollständiger Klassen und Member, die in abgeleiteten Klassen implementiert werden müssen. Er erzwingt einen Vertrag, dem abgeleitete Klassen folgen müssen, und stellt sicher, dass bestimmte Methoden und Eigenschaften implementiert werden. Die geeignete Verwendung des Schlüsselworts abstract fördert eine klare Abgrenzung der Verantwortlichkeiten zwischen Basis- und abgeleiteten Klassen.
Untersuchen Sie die Verwendung des Schlüsselworts virtual
Das schlüsselwort virtual in C# wird verwendet, um Methoden und Eigenschaften zu definieren, die in abgeleiteten Klassen überschrieben werden können. Eine virtuelle Methode oder Eigenschaft verfügt über eine Implementierung in der Basisklasse, kann aber in abgeleiteten Klassen erweitert oder geändert werden. Abgeleitete Klassen können virtuelle Member überschreiben, um ihre eigenen Implementierungen bereitzustellen.
Zum Beispiel:
public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("Animal makes a sound");
}
}
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Dog barks");
}
}
class Program
{
static void Main()
{
Animal animal = new Dog();
animal.MakeSound();
}
}
In diesem Beispiel definiert die Animal Klasse eine virtuelle Methode MakeSound, die eine generische Nachricht druckt. Die Dog Klasse erbt von Animal und überschreibt die MakeSound-Methode, um eine bestimmte Nachricht zu drucken. Wenn Sie ein Dog-Objekt erstellen und die MakeSound-Methode aufrufen, wird die außerkraftsetzungsimplementierung in der Dog Klasse ausgeführt.
Die folgenden Regeln beschreiben, wie sich das schlüsselwort virtual auf die Vererbung auswirkt:
- Virtuelle Methoden: Eine virtuelle Methode verfügt über eine Implementierung in der Basisklasse, kann aber in abgeleiteten Klassen überschrieben werden.
- Virtuelle Eigenschaften: Ähnlich wie virtuelle Methoden verfügen virtuelle Eigenschaften über eine Implementierung in der Basisklasse und können in abgeleiteten Klassen überschrieben werden.
Untersuchen Sie die Verwendung des Schlüsselworts sealed
Das sealed Schlüsselwort in C# wird verwendet, um zu verhindern, dass eine Klasse oder ein Klassenmitglied geerbt oder überschrieben wird. Wenn eine Klasse als sealedmarkiert ist, kann sie nicht als Basisklasse für andere Klassen verwendet werden. Wenn eine Methode als sealedmarkiert ist, kann sie in abgeleiteten Klassen nicht überschrieben werden.
Zum Beispiel:
public class BaseClass
{
public virtual void Method1()
{
Console.WriteLine("Method1 in BaseClass");
}
public virtual void Method2()
{
Console.WriteLine("Method2 in BaseClass");
}
}
public class DerivedClass : BaseClass
{
public sealed override void Method1()
{
Console.WriteLine("Method1 in DerivedClass");
}
public override void Method2()
{
Console.WriteLine("Method2 in DerivedClass");
}
}
public class FinalClass : DerivedClass
{
// This class can't override Method1 because it's sealed in DerivedClass
public override void Method2()
{
Console.WriteLine("Method2 in FinalClass");
}
}
In diesem Beispiel erbt die DerivedClass von der BaseClass und überschreibt die Method1 Methode und markiert sie als sealed. Die Method2-Methode wird auch in DerivedClass überschrieben, ist jedoch nicht versiegelt. Die FinalClass erbt von DerivedClass und versucht, die Method2-Methode außer Kraft zu setzen. Die Method1-Methode kann jedoch nicht überschrieben werden, da sie in DerivedClass versiegelt ist.
Die folgenden Regeln beschreiben, wie sich das schlüsselwort sealed auf die Vererbung auswirkt:
- Versiegelte Klassen: Eine versiegelte Klasse kann nicht als Basisklasse für andere Klassen verwendet werden. Sie verhindert die Vererbung von der versiegelten Klasse.
- Versiegelte Methoden: Eine versiegelte Methode kann in abgeleiteten Klassen nicht überschrieben werden. Sie verhindert eine weitere Änderung der Methode in abgeleiteten Klassen.
- Versiegelte Eigenschaften: Ähnlich wie bei versiegelten Methoden können versiegelte Eigenschaften in abgeleiteten Klassen nicht überschrieben werden.
Versiegelte Klassen und Methoden sind nützlich, wenn Sie eine weitere Erweiterung oder Änderung einer Klasse oder Methode verhindern möchten. Sie bieten eine Möglichkeit, die Vererbung einzuschränken und sicherzustellen, dass bestimmte Member unverändert bleiben.
Überprüfen der impliziten Vererbung vom Objekt
In C# erben alle Klassen implizit von der Object Klasse. Die Object Klasse definiert mehrere Methoden, die für alle Klassen verfügbar sind, z. B. ToString, Equalsund GetHashCode. Wenn eine Klasse nicht explizit von einer anderen Klasse erbt, erbt sie weiterhin standardmäßig von Object.
ToString: DieToString-Methode gibt eine Zeichenfolge zurück, die das aktuelle Objekt darstellt. Standardmäßig wird der vollqualifizierte Name der Klasse zurückgegeben.Equals: DieEquals-Methode vergleicht zwei Objekte für die Gleichheit. Standardmäßig werden die Verweise der Objekte verglichen.GetHashCode: DieGetHashCode-Methode gibt einen Hashcode für das aktuelle Objekt zurück. Standardmäßig wird der Hashcode der Objektreferenz zurückgegeben.
Betrachten Sie das folgende Codebeispiel, das drei Person Objekte erstellt und die geerbten ToString, Equalsund GetHashCode Methoden veranschaulicht:
Person person1 = new Person { Name = "Alice", Age = 30 };
Person person2 = new Person { Name = "Alice", Age = 30 };
Person person3 = person1;
Console.WriteLine(person1.ToString());
Console.WriteLine(person1.Equals(person2));
Console.WriteLine(person1.GetHashCode());
Console.WriteLine(person1.Equals(person3));
public class Person
{
public string? Name { get; set; }
public int Age { get; set; }
}
public class Employee : Person
{
public int EmployeeNumber { get; set; }
public decimal Salary { get; set; }
}
// Output: Person
// False
// 32854180
// True
In diesem Codebeispiel gibt die ToString-Methode den vollqualifizierten Namen der Person Klasse zurück, die den definierten Namespace enthält. Die erste Equals Methode vergleicht die Verweise der person1 und person2 Objekte und gibt Falsezurück. Die GetHashCode-Methode gibt den Hashcode des Verweises des person1 Objekts zurück. Anschließend vergleicht die Equals-Methode die Verweise der person1 und person3 Objekte und gibt Truezurück.
Zusammenfassung
Mit der Vererbung können abgeleitete Klassen Mitglieder der Basisklasse erben, die einen allgemeinen Satz von Attributen und Verhaltensweisen definieren. Abgeleitete Klassen können das Verhalten der Basisklasse erweitern oder ändern, indem neue Member hinzugefügt oder vorhandene Member überschrieben werden. Die Schlüsselwörter abstract, virtual und sealed werden verwendet, um zu steuern, wie Basisklassenmitglieder vererbt oder überschrieben werden. Die Sichtbarkeit geerbter Mitglieder wird durch Zugriffsmodifizierer wie public, protected, internal und private beeinflusst. Alle Klassen in C# erben implizit von der Object Klasse, die mehrere Methoden bereitstellt, z. B. ToString, Equalsund GetHashCode, die für alle Klassen verfügbar sind.