Freigeben über


Vererbung (C#-Programmierhandbuch)

Aktualisiert: Juli 2008

Vererbung ist, gemeinsam mit Kapselung und Polymorphie, eines der drei primären Merkmale (oder "Pfeiler") der objektorientierten Programmierung. Vererbung ermöglicht die Erstellung neuer Klassen, die in anderen Klassen definiertes Verhalten wieder verwenden, erweitern und ändern. Die Klasse, deren Member vererbt werden, wird Basisklasse genannt, und die Klasse, die diese Member erbt, wird abgeleitete Klasse genannt.

Hinweis:

Strukturen unterstützen keine Vererbung, sie können jedoch Schnittstellen implementieren. Weitere Informationen hierzu finden Sie unter Schnittstellen (C#-Programmierhandbuch).

Vom Konzept her ist eine abgeleitete Klasse eine Spezialisierung der Basisklasse. Eine Basisklasse Animal kann beispielsweise eine abgeleitete Klasse mit dem Namen Mammal und eine weitere abgeleitete Klasse mit dem Namen Reptile haben. Ein Mammal ist ein Animal, und ein Reptile ist ein Animal, jede abgeleitete Klasse stellt jedoch unterschiedliche Spezialisierungen der Basisklasse dar.

Wenn eine Klasse so definiert wird, dass sie von einer anderen Klasse abgeleitet wird, erhält die abgeleitete Klasse implizit alle Member der Basisklasse, mit Ausnahme ihrer Konstruktoren und Destruktoren. In der abgeleiteten Klasse wird dadurch der Code der Basisklasse wieder verwendet, ohne dass dieser erneut implementiert werden muss. In der abgeleiteten Klasse können zusätzliche Member hinzugefügt werden. Auf diese Weise erweitert die abgeleitete Klasse die Funktionalität der Basisklasse.

In der folgenden Abbildung ist die Klasse WorkItem dargestellt, die ein Arbeitselement in einem Geschäftsprozess darstellt. Wie alle Klassen ist diese Klasse von System.Object abgeleitet und erbt alle ihre Methoden. WorkItem fügt fünf eigene Member hinzu. Dazu gehört ein Konstruktor, da Konstruktoren nicht vererbt werden. ChangeRequest erbt von WorkItem und stellt eine bestimmte Art einer Arbeitsaufgabe dar. Die ChangeRequest-Klasse fügt den Membern, die sie von WorkItem und Object erbt, zwei weitere Member hinzu. Sie muss einen eigenen Konstruktor hinzufügen, und sie fügt weiterhin einen Member hinzu, der es ChangeRequest ermöglicht, mit dem ursprünglichen WorkItem verknüpft zu sein, für das die Änderung gilt.

Klassenvererbung

Klassenvererbung

Im folgenden Beispiel wird dargestellt, wie die in der vorherigen Abbildung veranschaulichten Klassenbeziehungen in C# ausgedrückt werden. Das Beispiel zeigt auch, wie WorkItem die virtuelle Methode Object.ToString überschreibt, und wie die Klasse ChangeRequest die WorkItem-Implementierung der Methode erbt.

// WorkItem implicitly inherits from Object class
public class WorkItem
{
    private static int nextID;
    protected int ID { get; set; }
    protected TimeSpan jobLength { get; set; }
    protected string Title { get; set; }
    protected string Description { get; set; }
    // Default constructor
    public WorkItem() 
    {
        ID = 0;
        Title = "Default title";
        Description = "Default description.";
        jobLength = new TimeSpan();
    }
    // Static constructor for static member.
    static WorkItem()
    {
        nextID = 0;
    }
    // Instance constructor.
    public WorkItem( string title, string desc, TimeSpan joblen)
    {
        this.ID = GetNextID();                
        this.Title = title;
        this.Description = desc;
        this.jobLength = joblen;
    }
    protected int GetNextID()
    {
       return ++nextID;
    }
    public void Update(string title, TimeSpan joblen)
    {
        this.Title = title;
        this.jobLength = joblen;
    }

    // Virtual method override.
    public override string ToString()
    {
        return String.Format("{0} - {1}", this.ID, this.Title); 
    }
}

// ChangeRequest derives from WorkItem and adds two of its own members.
public class ChangeRequest : WorkItem
{
    protected int originalItemID {get; set;}
    public ChangeRequest() { }
    public ChangeRequest(string title, string desc, TimeSpan jobLen, int originalID)
    {
        this.ID = GetNextID();
        this.Title = title;
        this.Description = desc;
        this.jobLength = jobLen;
        this.originalItemID = originalID;
    }
}

class Program
{
    static void Main()
    {
        WorkItem item = new WorkItem(                                
                        "Fix Bugs", 
                        "Fix all bugs in my source code branch",
                        new TimeSpan(3, 4, 0, 0));

        ChangeRequest change = new ChangeRequest("Change design of base class",
                                                 "Add members to base class",
                                                 new TimeSpan(4, 0, 0),
                                                 1);

        Console.WriteLine(item.ToString());

        // ChangeRequest inherits WorkItem's override of ToString
        Console.WriteLine(change.ToString()); 

        // Keep the console open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Output:
    1 - Fix Bugs
    2 - Change design of base class
*/

Abstrakte und virtuelle Methoden

Wenn in einer Basisklasse eine Methode als virtuell deklariert wird, kann die Methode in einer abgeleiteten Klasse mit einer eigenen Implementierung überschrieben werden. Wenn in einer Basisklasse ein Member als abstrakt deklariert wird, muss diese Methode in jeder nicht abstrakten Klasse, die direkt von dieser Klasse erbt, überschrieben werden. Wenn eine abgeleitete Klasse selbst abstrakt ist, erbt diese abstrakte Member, ohne sie zu implementieren. Abstrakte und virtuelle Member sind die Grundlage für Polymorphie, die das zweite primäre Merkmal der objektorientierten Programmierung darstellt. Weitere Informationen finden Sie unter Polymorphismus (C#-Programmierhandbuch).

Abstrakte Basisklassen

Eine Klasse kann als abstrakt deklariert werden, wenn eine direkte Instanziierung mittels des Schlüsselworts new verhindert werden soll. In diesem Fall kann die Klasse nur verwendet werden, wenn eine neue Klasse von ihr abgeleitet wird. Eine abstrakte Klasse kann eine oder mehrere Methodensignaturen enthalten, die selbst als abstrakt deklariert sind. Diese Signaturen geben die Parameter und den Rückgabewert an, haben jedoch keine Implementierung (Methodentext). Eine abstrakte Klasse muss keine abstrakte Member enthalten. Wenn eine Klasse jedoch abstrakte Member enthält, muss die Klasse als abstrakt deklariert sein. Abgeleitete Klassen, die selbst nicht abstrakt sind, müssen die Implementierung für jede abstrakte Methode aus einer abstrakten Basisklasse bereitstellen. Weitere Informationen finden Sie unter Abstrakte und versiegelte Klassen und Klassenmember (C#-Programmierhandbuch) und unter Entwurf abstrakter Klassen.

Schnittstellen

Eine Schnittstelle ist ein Referenztyp, der einer abstrakten Basisklasse ähnelt, die nur aus abstrakten Membern besteht. Wenn eine Klasse von einer Schnittstelle abgeleitet ist, muss diese eine Implementierung für alle Member dieser Schnittstelle bereitstellen. Ein Klasse kann viele Schnittstellen implementieren, obwohl sie nur von einer einzigen direkten Basisklasse abgeleitet sein kann.

Schnittstellen werden verwendet, um spezifische Fähigkeiten für Klassen zu definieren, die nicht notwendigerweise in einer "ist ein"-Beziehung zu einander stehen. Beispielsweise kann die Schnittstelle IEquatable[`1] durch jede Klasse oder Struktur implementiert werden, die es Clientcode ermöglichen muss, zu ermitteln, ob zwei Objekte des Typs äquivalent sind (dabei definiert allerdings die Äquivalenz). IEquatable<T> bedeutet nicht die gleiche Art von "ist ein"-Beziehung, die zwischen einer Basisklasse und einer abgeleiteten Klasse besteht (beispielsweise ist ein Mammal ein Animal). Weitere Informationen hierzu finden Sie unter Schnittstellen (C#-Programmierhandbuch).

Zugriff der abgeleiteten Klasse auf Member der Basisklasse

Eine abgeleitete Klasse hat Zugriff auf die öffentlichen, geschützten, internen und geschützten internen Member einer Basisklasse. Auch wenn eine abgeleitete Klasse die privaten Member einer Basisklasse erbt, kann sie nicht auf diese Member zugreifen. Diese privaten Member sind jedoch noch in der abgeleiteten Klasse vorhanden und können die gleichen Aufgaben übernehmen, die sie in der Basisklasse übernehmen würden. Wenn beispielsweise eine geschützte Basisklassenmethode auf ein privates Feld zugreift, muss dieses Feld in der abgeleiteten Klasse vorhanden sein, damit die vererbte Basisklassenmethode ordnungsgemäß funktioniert.

Verhindern weiterer Ableitung

Eine Klasse kann andere Klassen daran hindern, von ihr oder einem ihrer Member zu erben, indem sie oder der Member als versiegelt deklariert wird. Weitere Informationen hierzu finden Sie unter Abstrakte und versiegelte Klassen und Klassenmember (C#-Programmierhandbuch).

Verdecken von Basisklassenmembern in abgeleiteten Klassen

In einer abgeleiteten Klasse können Member der Basisklasse verdeckt werden, indem Member mit demselben Namen und derselben Signatur deklariert werden. Der new-Modifizierer kann verwendet werden, um explizit anzugeben, dass der Member nicht als Überschreibung des Basismembers vorgesehen ist. Die Verwendung von new ist nicht erforderlich. Es wird jedoch eine Compilerwarnung erstellt, wenn new nicht verwendet wird. Weitere Informationen finden Sie unter Versionsverwaltung mit den Schlüsselwörtern "override" und "new" (C#-Programmierhandbuch) und unter Wann müssen die Schlüsselwörter "override" und "new" verwendet werden? (C#-Programmierhandbuch).

Siehe auch

Konzepte

C#-Programmierhandbuch

Referenz

Klassen und Strukturen (C#-Programmierhandbuch)

class (C#-Referenz)

struct (C#-Referenz)

Änderungsprotokoll

Date

Versionsgeschichte

Grund

Juli 2008

Inhalt, eine Abbildung und neue Beispiele hinzugefügt.

Informationsergänzung.