CodeGym /Kurse /C# SELF /Methodenüberschreibung (override) in C#

Methodenüberschreibung (override) in C#

C# SELF
Level 20, Lektion 3
Verfügbar

1. Einführung

Stell dir vor, wir haben eine App zur Verwaltung von Tieren im Zoo (genau das Beispiel, das wir schon in den letzten Vorlesungen angefangen haben). Wir haben eine Basisklasse Animal mit der Methode MakeSound erstellt, damit alle Tiere irgendeinen Sound "machen" können.


public class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("Tier macht ein Geräusch.");
    }
}
        
Basisklasse mit virtueller Methode

Aber plötzlich merken wir, dass Löwe und Papagei ganz unterschiedliche Geräusche machen. Das universelle "Tier macht ein Geräusch" passt nicht mehr. Genau hier kommt das Überschreiben von Methoden ins Spiel. Du willst, dass jeder Nachfahre seinen eigenen Sound hat!

2. Syntax: Wie funktioniert override

Grundregeln

  • Um eine Methode zu überschreiben, muss sie in der Basisklasse als virtual (oder abstract) markiert sein.
  • In der abgeleiteten Klasse benutzt du das Schlüsselwort override vor der Methode mit derselben Signatur.

Beispiel: Löwen und Papageien

public class Lion : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Rrrrrr!");
    }
}

public class Parrot : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Polly ist doof!");
    }
}

Jetzt, wenn du eine Liste von Tieren erstellst und für jedes MakeSound aufrufst, "spricht" jedes auf seine eigene Art:

Animal[] zoo = new Animal[]
{
    new Lion(),
    new Parrot(),
    new Animal()
};

foreach (var animal in zoo)
{
    animal.MakeSound();
}
// Ausgabe:
// Rrrrrr!
// Polly ist doof!
// Tier macht ein Geräusch.
Wichtig: C# ruft genau die Implementierung der Methode auf, die dem echten ( run-time) Typ des Objekts entspricht, auch wenn die Variable als Animal deklariert ist!

3. Virtuelle Methodentabelle (v-table)

Wenn du virtual und override verwendest, erzeugt der Compiler für die Klasse eine spezielle "virtuelle Methodentabelle" (v-table).
Beim Aufruf einer Methode über eine Referenz auf die Basisklasse schaut die CLR in die Tabelle: Wurde diese Methode im Nachfahren überschrieben? Wenn ja – wird die Variante aus dem Nachfahren aufgerufen.
Das ist die "Magie" des späten Bindens (late binding) oder dynamischen Polymorphismus.

4. Alles zusammen: Wir entwickeln unsere App weiter

Lass uns noch eine Klasse hinzufügen:

public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Wuff-wuff!");
    }
}

Und wir nutzen das in unserem kleinen Tierverwaltungsprogramm:

Animal[] zoo = new Animal[]
{
    new Lion(),
    new Parrot(),
    new Dog()
};

foreach (var animal in zoo)
{
    animal.MakeSound();
}

Jetzt ist der Code viel flexibler und wartbarer geworden, und neue Tiere hinzuzufügen macht richtig Spaß!

5. Properties überschreiben und override mit Rückgabewert

Methoden sind nicht das Einzige, was du überschreiben kannst. Du kannst auch virtuelle Properties und Indexer überschreiben.

public class Animal
{
    public virtual string Name { get; set; } = "Tier";
}

public class Lion : Animal
{
    public override string Name { get; set; } = "Löwe";
}

Das ist besonders praktisch, wenn du Infos für eine bestimmte Art genauer machen willst.

6. Basisimplementierung mit base

Manchmal willst du das Verhalten der Basismethode erweitern, nicht komplett ersetzen.
Dafür rufst du die Implementierung der Basismethode mit dem Schlüsselwort base innerhalb der überschriebenen Methode auf.

public class Parrot : Animal
{
    public override void MakeSound()
    {
        base.MakeSound(); // "Tier macht ein Geräusch."
        Console.WriteLine("Polly ist doof!");
    }
}

In diesem Fall macht der Papagei erst das allgemeine "Zoo-Geräusch" und dann sein typisches "Polly ist doof!".

7. Praktischer Nutzen: Wo braucht man das?

Das Verständnis vom override-Mechanismus ist in fast jedem ernsthaften C#-Projekt wichtig, wo OOP intensiv genutzt wird.

  • Tiermodelle in unserem Zoo? Haben wir schon gemacht.
  • Eigene UI-Controls bauen: Du überschreibst Standard-Visual-Methoden und fügst deine eigene Logik hinzu.
  • Flexible Business-Logik: Du baust das "Skelett" des Verhaltens in Basisklassen und die Details in den Nachfahren.
  • Testing und Mocks: Methoden lassen sich easy durch Nachfahren für Unit-Tests "austauschen".
  • Plugins und Erweiterungen: Interface oder abstrakte Basisklasse, viele Implementierungen – und alles läuft dank richtigem Überschreiben.

8. sealed override und virtuelle Methoden in Ketten

Wenn du nicht willst, dass jemand weiter unten in der Hierarchie deine überschriebene Methode nochmal überschreibt, kannst du sealed override verwenden:

public class Base
{
    public virtual void Foo() { }
}

public class Middle : Base
{
    public sealed override void Foo() { }
}

public class Last : Middle
{
    public override void Foo() {} // Fehler – darf nicht überschrieben werden!
}

So kannst du die Überschreibungskette genau da "abschließen", wo es für die Systemfunktion wichtig ist.

9. Neue Methode (Schlüsselwort new)

Manchmal willst du in einem Nachfahren eine Methode mit derselben Signatur deklarieren, aber die Basismethode ist nicht virtual.
Dann kannst du das Schlüsselwort new verwenden – aber das ist kein Polymorphismus, sondern eher "Maskierung":

public class Animal
{
    public void MakeSound()
    {
        Console.WriteLine("Ich bin ein Tier!");
    }
}

public class Cat : Animal
{
    public new void MakeSound()
    {
        Console.WriteLine("Ich bin eine Katze!");
    }
}

Animal animal = new Cat();
animal.MakeSound(); // "Ich bin ein Tier!"
Cat cat = new Cat();
cat.MakeSound(); // "Ich bin eine Katze!"

Hier entscheidet der Typ der Variable beim Aufruf! Für echten dynamischen Polymorphismus solltest du immer virtual + override kombinieren.

10. Typische Fehler beim Überschreiben von Methoden

Fehler Nr. 1: Versuch, eine Methode zu überschreiben, die nicht als virtual, abstract oder override deklariert ist.
In C# kannst du normale Methoden nicht überschreiben. Wenn die Methode in der Basisklasse keinen speziellen Modifikator (virtual, abstract oder override) hat, führt der Versuch, override in der abgeleiteten Klasse zu schreiben, zu einem Compilerfehler.

Fehler Nr. 2: Signaturen der Methode stimmen nicht überein.
Damit eine Methode wirklich überschrieben wird, müssen Name, Rückgabetyp und Parameter exakt mit der Methode in der Basisklasse übereinstimmen. Schon die kleinste Abweichung (z.B. anderer Parametertyp) führt dazu, dass eine neue Methode entsteht, aber keine Überschreibung.

Fehler Nr. 3: Modifikator override vergessen.
Wenn du eine Methode mit derselben Signatur wie in der Basisklasse definierst, aber override nicht angibst, sieht der Compiler das nicht als Überschreibung. Das nennt man Method Hiding (wird separat behandelt). In dem Fall führt der Aufruf der Methode über eine Basistyp-Variable zu einem unerwarteten Ergebnis – es wird die Basismethode aufgerufen, nicht deine.

2
Aufgabe
C# SELF, Level 20, Lektion 3
Gesperrt
Polymorphismus mit Methodenüberschreibung
Polymorphismus mit Methodenüberschreibung
2
Aufgabe
C# SELF, Level 20, Lektion 3
Gesperrt
Verwendung der Basisimplementierung mit `base`
Verwendung der Basisimplementierung mit `base`
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION