Polymorphismus (C#-Programmierhandbuch)Polymorphism (C# Programming Guide)

Polymorphismus wird häufig nach der Kapselung und der Vererbung als die dritte Säule der objektorientierten Programmierung bezeichnet.Polymorphism is often referred to as the third pillar of object-oriented programming, after encapsulation and inheritance. Es handelt sich dabei um ein griechisches Wort, das "Vielgestaltigkeit" bedeutet und zwei verschiedene Aspekte umfasst:Polymorphism is a Greek word that means "many-shaped" and it has two distinct aspects:

  • In Methodenparametern, Auflistungen und Arrays können Objekte einer abgeleiteten Klasse zur Laufzeit als Objekte einer Basisklasse behandelt werden.At run time, objects of a derived class may be treated as objects of a base class in places such as method parameters and collections or arrays. In diesem Fall ist der deklarierte Typ des Objekts nicht mehr mit dem Laufzeittyp identisch.When this occurs, the object's declared type is no longer identical to its run-time type.

  • Basisklassen können virtuelle Methoden definieren und implementieren und können von abgeleiteten Klassen überschrieben werden, was bedeutet, dass sie ihre eigene Definition und Implementierung bereitstellen.Base classes may define and implement virtual methods, and derived classes can override them, which means they provide their own definition and implementation. Zur Laufzeit, wenn die Methode von Clientcode aufgerufen wird, sucht die CLR den Laufzeittyp des Objekts und ruft die Überschreibung der virtuellen Methode auf.At run-time, when client code calls the method, the CLR looks up the run-time type of the object, and invokes that override of the virtual method. In Ihrem Quellcode können Sie daher eine Methode in einer Basisklasse aufrufen und bewirken, dass die Methodenversion der abgeleiteten Klasse ausgeführt wird.Thus in your source code you can call a method on a base class, and cause a derived class's version of the method to be executed.

Dank virtueller Methoden können Sie auf einheitliche Weise mit Gruppen verwandter Objekte arbeiten.Virtual methods enable you to work with groups of related objects in a uniform way. Nehmen Sie beispielsweise an, Sie haben eine Zeichenanwendung, mit der ein Benutzer verschiedene Arten von Formen auf einer Zeichenoberfläche erstellen kann.For example, suppose you have a drawing application that enables a user to create various kinds of shapes on a drawing surface. Zur Kompilierzeit wissen Sie nicht, welche spezifischen Typen von Formen der Benutzer erstellen wird.You do not know at compile time which specific types of shapes the user will create. Die Anwendung muss jedoch alle verschiedenen Formentypen, die erstellt werden, nachverfolgen und diese als Antwort auf die Mausaktionen des Benutzers aktualisieren.However, the application has to keep track of all the various types of shapes that are created, and it has to update them in response to user mouse actions. Sie können Polymorphismus verwenden, um dieses Problem mithilfe von zwei einfachen Schritten zu lösen:You can use polymorphism to solve this problem in two basic steps:

  1. Erstellen Sie eine Klassenhierarchie, in der jede spezifische Formenklasse von einer gemeinsamen Basisklasse abgeleitet wird.Create a class hierarchy in which each specific shape class derives from a common base class.

  2. Verwenden Sie eine virtuelle Methode, um die entsprechende Methode in einer abgeleiteten Klasse durch einen einzigen Aufruf der Basisklassenmethode aufzurufen.Use a virtual method to invoke the appropriate method on any derived class through a single call to the base class method.

Erstellen Sie zuerst eine Basisklasse namens Shape und abgeleitete Klassen, wie z. B. Rectangle, Circle und Triangle.First, create a base class called Shape, and derived classes such as Rectangle, Circle, and Triangle. Geben Sie der Shape-Klasse eine virtuelle Methode namens Draw, und überschreiben Sie sie in jeder abgeleiteten Klasse, um die jeweilige Form zu zeichnen, die die Klasse darstellt.Give the Shape class a virtual method called Draw, and override it in each derived class to draw the particular shape that the class represents. Erstellen Sie ein List<Shape>-Objekt und fügen Sie einen Kreis, ein Dreieck und ein Rechteck hinzu.Create a List<Shape> object and add a Circle, Triangle and Rectangle to it. Um die Zeichenoberfläche zu aktualisieren, verwenden Sie eine foreach-Schleife, um die Liste zu durchlaufen und die Draw-Methode für jedes Shape-Objekt in der Liste aufzurufen.To update the drawing surface, use a foreach loop to iterate through the list and call the Draw method on each Shape object in the list. Obwohl jedes Objekt in der Liste einen deklarierten Shape-Typ aufweist, wird der Laufzeittyp (die überschriebene Version der Methode in jeder abgeleiteten Klasse) aufgerufen.Even though each object in the list has a declared type of Shape, it is the run-time type (the overridden version of the method in each derived class) that will be invoked.

using System;
using System.Collections.Generic;

public class Shape
{
    // A few example members
    public int X { get; private set; }
    public int Y { get; private set; }
    public int Height { get; set; }
    public int Width { get; set; }
   
    // Virtual method
    public virtual void Draw()
    {
        Console.WriteLine("Performing base class drawing tasks");
    }
}

class Circle : Shape
{
    public override void Draw()
    {
        // Code to draw a circle...
        Console.WriteLine("Drawing a circle");
        base.Draw();
    }
}
class Rectangle : Shape
{
    public override void Draw()
    {
        // Code to draw a rectangle...
        Console.WriteLine("Drawing a rectangle");
        base.Draw();
    }
}
class Triangle : Shape
{
    public override void Draw()
    {
        // Code to draw a triangle...
        Console.WriteLine("Drawing a triangle");
        base.Draw();
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Polymorphism at work #1: a Rectangle, Triangle and Circle
        // can all be used whereever a Shape is expected. No cast is
        // required because an implicit conversion exists from a derived 
        // class to its base class.
        var shapes = new List<Shape>
        {
            new Rectangle(),
            new Triangle(),
            new Circle()
        };

        // Polymorphism at work #2: the virtual method Draw is
        // invoked on each of the derived classes, not the base class.
        foreach (var shape in shapes)
        {
            shape.Draw();
        }

        // Keep the console open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }

}

/* Output:
    Drawing a rectangle
    Performing base class drawing tasks
    Drawing a triangle
    Performing base class drawing tasks
    Drawing a circle
    Performing base class drawing tasks
 */

In C# ist jeder Typ polymorph, da alle Typen, einschließlich benutzerdefinierten Typen, von Object erben.In C#, every type is polymorphic because all types, including user-defined types, inherit from Object.

Übersicht über PolymorphismusPolymorphism Overview

Virtuelle MemberVirtual Members

Wenn eine abgeleitete Klasse von einer Basisklasse erbt, erhält sie alle Methoden, Felder, Eigenschaften und Ereignisse der Basisklasse.When a derived class inherits from a base class, it gains all the methods, fields, properties and events of the base class. Der Designer der abgeleiteten Klassen kann entscheiden, ob:The designer of the derived class can choose whether to

  • virtuelle Member in der Basisklasse überschrieben werden sollenoverride virtual members in the base class,

  • die nächste Basisklassenmethoden vererbt ohne Überschreiben vererbt werden soll,inherit the closest base class method without overriding it

  • neue nicht virtuelle Member der Member definiert werden sollen, die die Basisklassenimplementierungen verbergen.define new non-virtual implementation of those members that hide the base class implementations

Eine abgeleitete Klasse kann einen Basisklassenmember nur überschreiben, wenn der Basisklassenmember als virtuell oder abstrakt deklariert ist.A derived class can override a base class member only if the base class member is declared as virtual or abstract. Der abgeleitete Member muss das override-Schlüsselwort verwenden, um explizit anzugeben, dass die Methode an dem virtuellen Aufruf beteiligt sein soll.The derived member must use the override keyword to explicitly indicate that the method is intended to participate in virtual invocation. Der folgende Code veranschaulicht dies:The following code provides an example:

public class BaseClass
{
    public virtual void DoWork() { }
    public virtual int WorkProperty
    {
        get { return 0; }
    }
}
public class DerivedClass : BaseClass
{
    public override void DoWork() { }
    public override int WorkProperty
    {
        get { return 0; }
    }
}

Felder können nicht virtuelle sein; nur Methoden, Eigenschaften, Ereignisse und Indexer können virtuell sein.Fields cannot be virtual; only methods, properties, events and indexers can be virtual. Wenn eine abgeleitete Klasse einen virtuellen Member überschreibt, wird dieser Member auch dann aufgerufen, wenn auf eine Instanz dieser Klasse als Instanz der Basisklasse zugegriffen wird.When a derived class overrides a virtual member, that member is called even when an instance of that class is being accessed as an instance of the base class. Der folgende Code veranschaulicht dies:The following code provides an example:

DerivedClass B = new DerivedClass();
B.DoWork();  // Calls the new method.

BaseClass A = (BaseClass)B;
A.DoWork();  // Also calls the new method.

Mithilfe virtueller Methoden und Eigenschaften können abgeleitete Klassen eine Basisklasse erweitern, ohne die Basisklassenimplementierung einer Methode verwenden zu müssen.Virtual methods and properties enable derived classes to extend a base class without needing to use the base class implementation of a method. Weitere Informationen finden Sie unter Versionsverwaltung mit den Schlüsselwörtern „override“ und „new“.For more information, see Versioning with the Override and New Keywords. Eine Schnittstelle bietet eine weitere Möglichkeit zur Definition einer Methode bzw. einer Gruppe von Methoden, deren Implementierung von abgeleiteten Klassen übernommen wird.An interface provides another way to define a method or set of methods whose implementation is left to derived classes. Weitere Informationen finden Sie unter Schnittstellen.For more information, see Interfaces.

Ausblenden von Basisklassenmembern für neue MemberHiding Base Class Members with New Members

Wenn Sie möchten, dass der abgeleitete Member denselben Namen wie ein Member in einer Basisklasse aufweist, jedoch nicht möchten, dass dieser an dem virtuellen Aufruf beteiligt ist, können Sie das new-Schlüsselwort verwenden.If you want your derived member to have the same name as a member in a base class, but you do not want it to participate in virtual invocation, you can use the new keyword. Das new-Schlüsselwort wird dem Rückgabetyp eines Klassenmembers vorangestellt, der ersetzt wird.The new keyword is put before the return type of a class member that is being replaced. Der folgende Code veranschaulicht dies:The following code provides an example:

public class BaseClass
{
    public void DoWork() { WorkField++; }
    public int WorkField;
    public int WorkProperty
    {
        get { return 0; }
    }
}

public class DerivedClass : BaseClass
{
    public new void DoWork() { WorkField++; }
    public new int WorkField;
    public new int WorkProperty
    {
        get { return 0; }
    }
}

Auf ausgeblendete Klassenmember kann vom Clientcode immer noch zugegriffen werden, indem die Instanz der abgeleiteten Klasse in eine Instanz der Basisklasse umgewandelt wird.Hidden base class members can still be accessed from client code by casting the instance of the derived class to an instance of the base class. Beispiel:For example:

DerivedClass B = new DerivedClass();
B.DoWork();  // Calls the new method.

BaseClass A = (BaseClass)B;
A.DoWork();  // Calls the old method.

Verhindern, dass abgeleitete Klassen virtuelle Member überschreibenPreventing Derived Classes from Overriding Virtual Members

Virtuelle Member bleiben praktisch unendlich erhalten, unabhängig davon, wie viele Klassen zwischen dem virtuellen Member und der Klasse deklariert wurden, die diesen ursprünglich deklariert hat.Virtual members remain virtual indefinitely, regardless of how many classes have been declared between the virtual member and the class that originally declared it. Wenn Klasse A einen virtuellen Member deklariert und Klasse B von A erbt und Klasse C von B erbt, so erbt C den virtuellen Member und hat die Option, diesen zu überschreiben, unabhängig davon, ob Klasse B das Überschreibung für diesen Member deklariert hat.If class A declares a virtual member, and class B derives from A, and class C derives from B, class C inherits the virtual member, and has the option to override it, regardless of whether class B declared an override for that member. Der folgende Code veranschaulicht dies:The following code provides an example:

public class A
{
    public virtual void DoWork() { }
}
public class B : A
{
    public override void DoWork() { }
}

Eine abgeleitete Klasse kann die virtuelle Vererbung stoppen, indem das Überschreiben als versiegelt deklariert wird.A derived class can stop virtual inheritance by declaring an override as sealed. Hierfür muss das sealed-Schlüsselwort in der Klassenmemberdeklaration vor das override-Schlüsselwort gestellt werden.This requires putting the sealed keyword before the override keyword in the class member declaration. Der folgende Code veranschaulicht dies:The following code provides an example:

public class C : B
{
    public sealed override void DoWork() { }
}

Im vorherigen Beispiel ist die Methode DoWork für jede von C abgeleitete Klasse nicht mehr virtuell. Sie ist weiterhin virtuell für Instanzen von C, selbst wenn diese in Typ B oder Typ A umgewandelt werden. Versiegelte Methoden können, wie im folgenden Beispiel gezeigt, mithilfe des new-Schlüsselworts durch abgeleitete Klassen ersetzt werden:In the previous example, the method DoWork is no longer virtual to any class derived from C. It is still virtual for instances of C, even if they are cast to type B or type A. Sealed methods can be replaced by derived classes by using the new keyword, as the following example shows:

public class D : C
{
    public new void DoWork() { }
}

In diesem Fall wird, wenn DoWork für D mithilfe einer Variablen vom Typ D aufgerufen wird, das neue DoWork aufgerufen.In this case, if DoWork is called on D using a variable of type D, the new DoWork is called. Wenn eine Variable vom Typ C, B oder A zum Zugreifen auf eine Instanz von D verwendet wird, befolgt ein Aufruf von DoWork die Regeln der virtuellen Vererbung, und diese Aufrufe werden an die Implementierung von DoWork für Klasse C weitergeleitet.If a variable of type C, B, or A is used to access an instance of D, a call to DoWork will follow the rules of virtual inheritance, routing those calls to the implementation of DoWork on class C.

Zugreifen auf virtuelle Basisklassenmember von abgeleiteten Klassen ausAccessing Base Class Virtual Members from Derived Classes

Eine abgeleitete Klasse, die eine Methode oder Eigenschaft ersetzt oder überschrieben hat, kann immer noch auf die Methode oder Eigenschaft in der Basisklasse mithilfe des base-Schlüsselworts zugreifen.A derived class that has replaced or overridden a method or property can still access the method or property on the base class using the base keyword. Der folgende Code veranschaulicht dies:The following code provides an example:

public class Base
{
    public virtual void DoWork() {/*...*/ }
}
public class Derived : Base
{
    public override void DoWork()
    {
        //Perform Derived's work here
        //...
        // Call DoWork on base class
        base.DoWork();
    }
}

Weitere Informationen finden Sie unter base.For more information, see base.

Hinweis

Es wird empfohlen, dass virtuelle Member base verwenden, um die Basisklassenimplementierung dieses Members in seiner eigenen Implementierung aufzurufen.It is recommended that virtual members use base to call the base class implementation of that member in their own implementation. Durch Zulassen des Basisklassenverhaltens kann sich die abgeleitete Klasse auf die Implementierung von Verhalten konzentrieren, das spezifisch für die abgeleitete Klasse ist.Letting the base class behavior occur enables the derived class to concentrate on implementing behavior specific to the derived class. Wenn die Basisklassenimplementierung nicht aufgerufen wird, liegt es an der abgeleiteten Klasse, ihr Verhalten kompatibel mit dem Verhalten der Basisklasse zu gestalten.If the base class implementation is not called, it is up to the derived class to make their behavior compatible with the behavior of the base class.

In diesem AbschnittIn This Section

Siehe auchSee Also

C#-ProgrammierhandbuchC# Programming Guide
C#-ProgrammierhandbuchC# Programming Guide
VererbungInheritance
Abstrakte und versiegelte Klassen und KlassenmemberAbstract and Sealed Classes and Class Members
MethodenMethods
EreignisseEvents
EigenschaftenProperties
IndexerIndexers
TypenTypes