Menu
Coddy logo textTech

Compile- vs. Runtime-Polymorphismus

Teil des Abschnitts Objektorientierte Programmierung der C#-Journey von Coddy — Lektion 25 von 70.

Polymorphismus bedeutet „viele Formen“ – die Fähigkeit desselben Codes, sich je nach Kontext unterschiedlich zu verhalten. C# unterstützt zwei verschiedene Arten von Polymorphismus, und das Verständnis darüber, wann jede davon aufgelöst wird, hilft Ihnen dabei, flexibleren Code zu schreiben.

Kompilierzeit-Polymorphismus (auch statische Polymorphie genannt) wird vom Compiler aufgelöst, bevor Ihr Programm ausgeführt wird. Methodenüberladung ist das primäre Beispiel – mehrere Methoden teilen sich denselben Namen, haben aber unterschiedliche Parameter:

public class Calculator
{
    public int Add(int a, int b) => a + b;
    public double Add(double a, double b) => a + b;
}

var calc = new Calculator();
calc.Add(5, 3);       // Compiler wählt die int-Version
calc.Add(5.0, 3.0);   // Compiler wählt die double-Version

Der Compiler prüft die Argumenttypen und wählt die korrekte Methode zur Kompilierzeit aus. Diese Entscheidung steht fest, bevor das Programm jemals ausgeführt wird.

Laufzeitpolymorphismus (dynamische Polymorphie) wird aufgelöst, während das Programm läuft. Dies geschieht mit virtual und override Methoden – der tatsächliche Typ des Objekts bestimmt, welche Methode ausgeführt wird:

Animal pet = new Dog();  // Als Animal deklariert, tatsächlich ein Dog
pet.Speak();             // Ruft Speak() von Dog zur Laufzeit auf

Der Compiler weiß nicht, welches Speak() ausgeführt wird – diese Entscheidung fällt zur Laufzeit basierend auf dem tatsächlichen Typ des Objekts. Das ist es, was vererbungsbasierte Polymorphie so mächtig macht, um flexible, erweiterbare Systeme zu entwickeln.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Konvertersystem bauen, das beide Arten von Polymorphismus in Aktion demonstriert. Sie werden eine Klasse erstellen, die Methodenüberladung (Kompilierzeit-Polymorphismus) zusammen mit einer Vererbungshierarchie verwendet, die virtuelle/überschreibende Methoden (Laufzeit-Polymorphismus) nutzt.

Sie werden Ihren Code über vier Dateien organisieren:

  • Converter.cs: Definieren Sie eine Converter-Klasse im Namespace Conversion. Diese Klasse demonstriert Kompilierzeit-Polymorphismus durch Methodenüberladung. Erstellen Sie drei überladene Convert-Methoden:
    • Convert(int value) gibt "Integer: {value}" zurück
    • Convert(double value) gibt "Double: {value}" zurück
    • Convert(string value) gibt "String: {value}" zurück
  • Shape.cs: Definieren Sie eine Basisklasse Shape im Namespace Conversion. Diese Klasse hat eine Eigenschaft Name (string) und einen Konstruktor, der diese setzt. Fügen Sie eine virtual Methode namens Describe() hinzu, die "This is a {Name}" zurückgibt.
  • Circle.cs: Definieren Sie eine Klasse Circle im Namespace Conversion, die von Shape erbt. Fügen Sie eine Eigenschaft Radius (double) hinzu. Der Konstruktor akzeptiert einen Radius und übergibt "Circle" an den Basis-Konstruktor. Überschreiben Sie Describe(), um "This is a Circle with radius {Radius}" zurückzugeben.
  • Program.cs: Demonstrieren Sie in Ihrer Hauptdatei beide Arten von Polymorphismus. Erstellen Sie zuerst einen Converter und rufen Sie alle drei überladenen Methoden mit Eingabewerten auf. Erstellen Sie dann einen Circle, speichern Sie ihn in einer Shape-Variablen und rufen Sie Describe() auf, um Laufzeit-Polymorphismus zu zeigen.

Sie erhalten vier Eingaben:

  • Einen Integer-Wert
  • Einen Double-Wert
  • Einen String-Wert
  • Einen Kreisradius (double)

Geben Sie die Ausgabe in diesem Format aus:

Compile-time Polymorphism:
{Convert(int) result}
{Convert(double) result}
{Convert(string) result}
Runtime Polymorphism:
{Describe() result from Shape variable holding Circle}

Wenn die Eingaben beispielsweise 42, 3.14, Hello und 5.5 sind, sollte die Ausgabe wie folgt aussehen:

Compile-time Polymorphism:
Integer: 42
Double: 3.14
String: Hello
Runtime Polymorphism:
This is a Circle with radius 5.5

Beachten Sie den entscheidenden Unterschied: Der Compiler entscheidet zur Kompilierzeit anhand der Argumenttypen, welche Convert-Methode aufgerufen werden soll, während die Describe()-Methode zur Laufzeit basierend auf dem tatsächlichen Objekttyp aufgelöst wird, obwohl sie in einer Shape-Variablen gespeichert ist!

Spickzettel

Polymorphismus bedeutet „viele Formen“ – die Fähigkeit desselben Codes, sich je nach Kontext unterschiedlich zu verhalten.

Kompilierzeit-Polymorphismus (statischer Polymorphismus) wird vom Compiler aufgelöst, bevor das Programm ausgeführt wird. Methodenüberladung ist das primäre Beispiel:

public class Calculator
{
    public int Add(int a, int b) => a + b;
    public double Add(double a, double b) => a + b;
}

var calc = new Calculator();
calc.Add(5, 3);       // Compiler wählt die int-Version
calc.Add(5.0, 3.0);   // Compiler wählt die double-Version

Der Compiler prüft die Argumenttypen und wählt die korrekte Methode zur Kompilierzeit aus.

Laufzeit-Polymorphismus (dynamischer Polymorphismus) wird während der Programmausführung mithilfe von virtual- und override-Methoden aufgelöst:

Animal pet = new Dog();  // Als Animal deklariert, tatsächlich ein Dog
pet.Speak();             // Ruft Speak() von Dog zur Laufzeit auf

Der tatsächliche Typ des Objekts bestimmt, welche Methode zur Laufzeit ausgeführt wird, nicht der deklarierte Variablentyp.

Probier es selbst

using System;
using Conversion;

class Program
{
    public static void Main(string[] args)
    {
        // Eingaben lesen
        int intValue = Convert.ToInt32(Console.ReadLine());
        double doubleValue = Convert.ToDouble(Console.ReadLine());
        string stringValue = Console.ReadLine();
        double radius = Convert.ToDouble(Console.ReadLine());

        // TODO: Kompilierzeit-Polymorphismus demonstrieren
        // Erstellen Sie ein Converter-Objekt und rufen Sie alle drei überladenen Convert-Methoden auf
        Console.WriteLine("Compile-time Polymorphism:");
        // Rufen Sie Convert mit intValue, doubleValue und stringValue auf

        // TODO: Laufzeit-Polymorphismus demonstrieren
        // Erstellen Sie ein Circle-Objekt und speichern Sie es in einer Shape-Variable
        // Rufen Sie dann Describe() auf der Shape-Variable auf
        Console.WriteLine("Runtime Polymorphism:");
        // Circle erstellen und Describe() aufrufen
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung