CodeGym /Kurse /C# SELF /Das Konzept der Vererbung

Das Konzept der Vererbung

C# SELF
Level 20 , Lektion 0
Verfügbar

1. Einführung

Vererbung in der Programmierung ist ziemlich ähnlich wie Vererbung im echten Leben. Zum Beispiel kannst du von deinen Eltern die Augenfarbe, die Nasenform oder sogar das Talent zum Zeichnen erben. Du bekommst diese Eigenschaften "standardmäßig" und musst sie nicht von Grund auf neu erschaffen. Trotzdem kannst du deine eigenen, einzigartigen Eigenschaften entwickeln, die deine Eltern nicht haben.

In der Programmierung läuft das ähnlich ab:

  • Eine Klasse (wir nennen sie Basisklasse oder Elternklasse, manchmal auch Superklasse) definiert gemeinsame Eigenschaften (Properties) und Verhalten (Methoden), die alle ihre "Nachkommen" haben.
  • Eine andere Klasse (genannt abgeleitete Klasse oder Kindklasse, manchmal Subklasse) erbt all diese gemeinsamen Merkmale vom Elternteil. Sie bekommt automatisch alle public und protected Properties und Methoden der Basisklasse. Sie muss sie nicht nochmal deklarieren.
  • Die abgeleitete Klasse kann aber auch ihre eigenen, einzigartigen Properties und Methoden hinzufügen, die die Elternklasse nicht hat.
  • Manchmal kann die abgeleitete Klasse sogar das Verhalten geerbter Methoden ändern (aber dazu kommen wir in späteren Vorlesungen, das nennt man Polymorphismus).

Das Schlüsselkonzept der Vererbung drückt sich durch den Satz "ist-ein" (is-a relationship) aus. Stell dir vor, du schreibst ein Spiel mit Magiern, Kriegern und Bogenschützen:

  • Krieger ist ein Charakter.
  • Magier ist ein Charakter.
  • Bogenschütze ist ein Charakter.

Wenn Krieger ein Charakter ist, dann muss er alles haben, was jeder Charakter hat, plus etwas Eigenes, das nur für den Krieger gilt.

2. Syntax der Vererbung

Lass uns ein Beispiel anschauen und ein bisschen coden.

Grundlagen der Syntax


// Basisklasse
public class Animal
{
    public string Name { get; set; }

    public void Move()
    {
        Console.WriteLine($"{Name} bewegt sich.");
    }
}

// Kindklasse
public class Dog : Animal
{
    public void Bark()
    {
        Console.WriteLine($"{Name} bellt: Wuff!");
    }
}

Achte auf den Doppelpunkt nach dem Klassennamen Dog. Hier sagen wir: Dog erbt alles, was Animal hat.

Alles, was Animal als public und protected hat, bekommt Dog!

Verwendung von Vererbung

Probieren wir diese Klassen in unserer Konsolenanwendung aus:


var dog = new Dog();
dog.Name = "Sharik"; // Property Name von Animal geerbt
dog.Move();          // Methode Move von Animal geerbt
dog.Bark();          // eigene Methode von Dog

// Ausgabe:
// Sharik bewegt sich.
// Sharik bellt: Wuff!

Du kannst auch eine Katze erstellen, um den "Zoo" etwas bunter zu machen:

public class Cat : Animal
{
    public void Meow()
    {
        Console.WriteLine($"{Name} miaut: Miau!");
    }
}

var cat = new Cat();
cat.Name = "Murka";
cat.Move();
cat.Meow();

3. Wie Vererbung Arbeit spart

Wenn du mehrere ähnliche Entitäten hast, musst du den Code nicht immer wieder kopieren. Vererbung ist wie eine Master-Kopie: Du definierst die Logik einmal, und alle Nachkommen bekommen sie.

Visualisierung: Vererbungsbaum


.   Animal
     /    \
  Dog    Cat
Vererbungsdiagramm der Klassen
Klasse Property Name Methode Move Eigene Methode
Animal + + -
Dog + + Bark()
Cat + + Meow()

Noch ein Beispiel – Anwendung erweitern

Stell dir vor, wir wollen ein System für verschiedene Typen von Menschen bauen. Erinnern wir uns an den alten Ansatz:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

// Jetzt fügen wir einen Mitarbeiter hinzu
public class Employee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Position { get; set; }
}

Nicht sehr praktisch! Die Namensdaten werden dupliziert. Mit Vererbung macht man es richtig:


public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Employee : Person
{
    public string Position { get; set; }
}

public class Student : Person
{
    public int Grade { get; set; }
}
Vererbung zur Beseitigung von Code-Duplikaten

Jetzt haben Employee und Student schon FirstName und LastName – kein zweites Mal schreiben nötig. Du kannst dir vorstellen, wie du das System jetzt easy für verschiedene Rollen erweiterst.

Das ist die Magie der Vererbung: Wir beschreiben die gemeinsamen Merkmale einmal in der Basisklasse und "erweitern" dann die Funktionalität in den abgeleiteten Klassen, indem wir spezifische Details hinzufügen.

4. Vorteile der Vererbung

Code-Wiederverwendung (Code Reusability): Das ist der offensichtlichste Vorteil. Du musst denselben Code nicht an mehreren Stellen schreiben. Einmal geschrieben – oft benutzt. Dein Code wird trockener und sauberer (in der Programmierwelt sagt man "Don't Repeat Yourself" – DRY, "Wiederhole dich nicht").

Einfachere Wartung (Easier Maintenance): Wenn du die Logik fürs Bewegen ändern willst, änderst du sie nur an einer Stelle – in der Basisklasse Animal. Alle abgeleiteten Klassen bekommen die Änderung automatisch. Stell dir vor, wie viel Zeit das in einem großen Projekt spart!

Hierarchien erstellen (Creating Hierarchies): Vererbung erlaubt es, "ist-ein"-Beziehungen aus der echten Welt zu modellieren und logische, verständliche Strukturen zu bauen. Krieger ist ein Charakter, Magier ist ein Charakter. Das macht deinen Code strukturierter und leichter verständlich.

Grundlage für Polymorphismus: Auch wenn wir Polymorphismus noch nicht im Detail behandelt haben, ist Vererbung die Basis dafür. Polymorphismus erlaubt es dir, mit Objekten verschiedener abgeleiteter Klassen über das gemeinsame Interface der Basisklasse zu arbeiten. Zum Beispiel kannst du eine Liste aller Animals haben (egal ob Dog, Cat oder andere Tiere) und bei allen die Methode Move aufrufen, ohne dich um den konkreten Typ zu kümmern. Das ist richtig mächtig, und wir kommen noch darauf zurück!

5. Feinheiten und Besonderheiten der Vererbung

Einfache Vererbung in C#: Im Gegensatz zu manchen anderen Sprachen (z.B. C++) unterstützt C# nur einfache Vererbung. Das heißt, eine Klasse kann nur von einer Basisklasse erben. Du kannst nicht gleichzeitig von Animal und zum Beispiel von Vehicle (wenn es so eine Klasse gäbe) erben.

Alle Klassen erben implizit von object: Fun Fact! Wenn du keine Basisklasse explizit angibst, erbt deine Klasse automatisch von System.Object. Das ist die grundlegendste Klasse in .NET und stellt einige fundamentale Methoden bereit, wie ToString(), Equals(), GetHashCode(). Wenn du also ToString() in deinen Klassen überschreibst, überschreibst du eigentlich eine Methode, die du von object geerbt hast!

Konstruktoren werden nicht vererbt: Die abgeleitete Klasse erbt keine Konstruktoren der Basisklasse. Du musst Konstruktoren explizit in der abgeleiteten Klasse definieren. Wenn die Basisklasse einen Konstruktor mit Parametern hat, MUSST du einen der Konstruktoren der Basisklasse aus dem Konstruktor der abgeleiteten Klasse aufrufen. Das machst du mit dem Schlüsselwort base.

Private Members sind nicht zugänglich: private Members der Basisklasse sind in der abgeleiteten Klasse nicht direkt zugänglich. Sie existieren im Objekt, aber du kannst sie im Code der abgeleiteten Klasse nicht per Namen ansprechen. Wenn du willst, dass Members für abgeleitete Klassen, aber nicht für die ganze Welt zugänglich sind, verwende den Zugriffsmodifizierer protected.

6. Visualisierung der Hierarchie

Um Vererbungsbeziehungen besser zu verstehen, nutzt man oft Diagramme. Eines der bekanntesten ist das Klassendiagramm aus UML (Unified Modeling Language). Für das einfache Beispiel mit Tieren sieht es so aus:

classDiagram
    class Animal {
        + string Name
        + Move()
    }

    class Dog {
        + Bark()
    }

    class Cat {
        + Meow()
    }

    Animal <|-- Dog : inherits
    Animal <|-- Cat : inherits
UML-Klassendiagramm für das Vererbungsbeispiel

Im Diagramm bedeutet der Pfeil mit dem unausgefüllten Dreieck (von Dog zu Animal, von Cat zu Animal) eine Vererbungsbeziehung: "ist-ein" (is-a relationship).

7. Praktische Anwendung von Vererbung

Vererbung ist nicht nur ein akademisches Konzept, sondern eine der Säulen der modernen Programmierung, die in echten Projekten ständig genutzt wird:

GUI-Entwicklung (Graphical User Interface): In WPF, WinForms, MAUI (Frameworks für Desktop-Apps auf .NET) erben fast alle Controls (Buttons, Textfelder, Fenster) von einer gemeinsamen Basisklasse Control oder UIElement. Dadurch haben sie gemeinsame Properties wie Größe, Position, Sichtbarkeit und gemeinsame Methoden wie Event-Handling.
Zum Beispiel: Button ist ein Control, und TextBox ist ein Control.

Game Engines: Vererbung ist perfekt, um Hierarchien von Spielobjekten zu bauen: GameObjectCharacterPlayer/Enemy oder VehicleCar/Motorcycle.

Arbeiten mit Datenbanken (ORM): In Frameworks wie Entity Framework Core definierst du oft eine Basisklasse für alle deine Entities, z.B. BaseEntity, die Properties wie Id (Datenbank-ID) oder CreatedAt (Erstellungsdatum) enthält. Alle konkreten Entities (z.B. User, Product, Order) erben von BaseEntity und bekommen diese Properties automatisch.

Testing: Vererbung wird in Test-Frameworks (wie xUnit, NUnit) genutzt, wo du Basistestklassen mit gemeinsamer Initialisierungs- und Aufräumlogik erstellen kannst, von denen konkrete Testklassen erben.

Bibliotheken und Frameworks: Die .NET-Standardbibliothek nutzt Vererbung selbst sehr intensiv. Viele Collections und Typen erben von gemeinsamen Basisklassen oder implementieren gemeinsame Interfaces (dazu später mehr).

In C#- und .NET-Bewerbungsgesprächen sind Fragen zu Vererbung, ihren Prinzipien (DRY, "is-a") und zu ihren Unterschieden zu anderen Konzepten (wie Komposition oder Interfaces) absolute Basics und kommen sehr oft dran. Nicht nur erklären zu können, was das ist, sondern auch Beispiele aus dem echten Leben oder Code zu bringen, ist ein sehr wertvoller Skill.

Du siehst also: Vererbung ist nicht einfach nur ein "Feature" der Sprache, sondern ein mächtiges Werkzeug, um Code zu strukturieren, Duplikate zu vermeiden und logisch zusammenhängende Systeme zu bauen. Das ist der Schlüssel zu skalierbarem und wartbarem Code.

Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION