C# Komposition Vererbung: Wann was nutzen? Einfach erklärt
Vererbung oder Komposition in C#? Dieser Artikel erklärt den Unterschied und zeigt, wann welche Methode für dein Projekt die bessere Wahl ist.
Von Marcel Schmidtpeter 11. Aug. 2026
Stell dir vor, du baust ein Rollenspiel in C#. Du hast eine Klasse `Character` für die Spielfigur und möchtest jetzt einen `Warrior` (Krieger) und einen `Mage` (Magier) erstellen. Die naheliegende Lösung? Vererbung - der `Warrior` erbt von `Character`.
Aber was passiert, wenn du plötzlich einen `FlyingMage` brauchst, der fliegen kann UND zaubern? Und zeitgleich einen `FlyingWarrior`? Schnell hast du ein unübersichtliches Vererbungs-Chaos.
Genau hier kommt Komposition ins Spiel. Ob du Azubi im ersten Lehrjahr, Informatik-Student oder Berufseinsteiger bist - das Thema C# Komposition Vererbung wirst du ständig antreffen. Es ist eine der wichtigsten Designentscheidungen in der objektorientierten Programmierung.
Was ist Vererbung in C#?
Vererbung (engl. *Inheritance*) bedeutet, dass eine Klasse Eigenschaften und Methoden einer anderen Klasse übernimmt. Die abgeleitete Klasse ("Kind") erbt dabei von der Basisklasse ("Eltern").
Stell dir die Biologie vor: Ein Hund ist ein Tier. Er erbt alle Eigenschaften von "Tier" (hat Beine, kann fressen) und fügt eigene hinzu (bellt). In C# schreibst du das mit einem Doppelpunkt:
public class Character
{
public string Name { get; set; }
public int Health { get; set; }
public void TakeDamage(int amount)
{
Health -= amount;
}
}
// Warrior erbt von Character
public class Warrior : Character
{
public int Armor { get; set; }
public void BlockAttack()
{
Console.WriteLine($"{Name} blockiert!");
}
}Der `Warrior` hat automatisch `Name`, `Health` und `TakeDamage` - ohne dass du sie neu schreiben musst. Das spart Code und wirkt auf den ersten Blick elegant.
Wichtig: Vererbung modelliert immer eine "ist-ein"-Beziehung (is-a). Ein Warrior *ist ein* Character. Mehr zu den Mechaniken wie `virtual` und `override` findest du in unserem Beitrag zu C# base virtual override.
Was ist Komposition in C#?
Komposition bedeutet, dass eine Klasse andere Objekte als Felder oder Eigenschaften enthält. Statt zu erben, "hat" die Klasse also ein anderes Objekt. Das ist die "hat-ein"-Beziehung (has-a).
Stell dir ein Auto vor: Es *hat* einen Motor, es *ist* aber kein Motor. Wenn der Motor kaputtgeht, ist das Auto nutzlos. Das nennt man Komposition - das Teil existiert nicht ohne das Ganze. Im Gegensatz dazu steht die schwächere Aggregation, bei der Teile unabhängig existieren können.
public class Weapon
{
public string Name { get; set; }
public int Damage { get; set; }
public void Strike()
{
Console.WriteLine($"{Name} trifft fuer {Damage} Schaden!");
}
}
public class Character
{
public string Name { get; set; }
public Weapon CurrentWeapon { get; set; } // Komposition
public void Attack()
{
CurrentWeapon.Strike();
}
}Der `Character` delegiert den Angriff an seine Waffe. Warum? Er muss sich nicht darum kümmern, *wie* die Waffe trifft - das ist allein die Aufgabe der `Weapon`-Klasse.
C# Komposition Vererbung im direkten Vergleich
Beide Konzepte dienen der Wiederverwendung von Code (Code Reuse), funktionieren aber grundverschieden. Die offizielle C#-Dokumentation auf Microsoft Learn behandelt beide Ansätze ausführlich.
Kriterium | Vererbung | Komposition |
Beziehung | "ist-ein" (is-a) | "hat-ein" (has-a) |
Flexibilität | Starr (festgelegt zur Kompilierzeit) | Dynamisch (austauschbar zur Laufzeit) |
Kopplung | Stark (enge Abhängigkeit) | Schwach (lose gekoppelt) |
Änderbarkeit | Schwer (Basisklasse ändern = alle Kinder ändern) | Leicht (nur eine Klasse ändern) |
Mehrfachvererbung | Nicht möglich in C# | Problemlos möglich |
Typbeziehung | Abgeleitete Klasse IST Basisklasse | Keine Typbeziehung |
Merke: "Favor composition over inheritance" (Bevorzuge Komposition gegenüber Vererbung). Dieser Grundsatz der sogenannten Gang of Four (vier Autoren klassischer Entwurfsmuster) gilt seit 1994.
Wann nutzt du C# Komposition und wann Vererbung?
Nutze Vererbung, wenn eine echte Untertyp-Beziehung (Subtyping) vorliegt und sich das Liskov-Substitutionsprinzip erfüllen lässt. Das bedeutet: Überall wo die Basisklasse erwartet wird, muss die abgeleitete Klasse funktionieren - ohne Überraschungen.
// Gut: Echte ist-ein-Beziehung
public abstract class Shape
{
public abstract double CalculateArea();
}
public class Circle : Shape
{
public double Radius { get; set; }
public override double CalculateArea()
{
return Math.PI * Radius * Radius;
}
}Ein Kreis ist wirklich eine geometrische Form. Das macht Sinn und nutzt Polymorphie (Vielgestaltigkeit).
Nutze Komposition, wenn du Verhalten (Behavior) flexibel kombinieren willst. Wenn verschiedene Klassen unterschiedliche Kombinationen von Fähigkeiten brauchen, stößt du mit Vererbung schnell an die Grenze. Das nennt man das Klassenexplosions-Problem:
// Schlecht: Klassenexplosion durch Vererbung
public class FlyingMage : Character { }
public class FlyingWarrior : Character { }
public class SwimmingMage : Character { }
public class SwimmingWarrior : Character { }
public class FlyingSwimmingMage : Character { }
// ... es wird immer schlimmerPraxisbeispiel: Ein flexibles Charaktersystem
Hier ist ein vollständiges Beispiel mit Interfaces für verschiedene Fähigkeiten. So kombinierst du Verhalten frei, ohne eine Klassenexplosion auszulösen:
using System;
public interface ICanFly
{
void Fly();
}
public interface ICanSwim
{
void Swim();
}
public interface ICanCastSpells
{
void CastSpell();
}
public class FlyBehavior : ICanFly
{
public void Fly()
{
Console.WriteLine("Hebt ab!");
}
}
public class SwimBehavior : ICanSwim
{
public void Swim()
{
Console.WriteLine("Schwimmt los!");
}
}
public class SpellBehavior : ICanCastSpells
{
public void CastSpell()
{
Console.WriteLine("Zaubert Feuerball!");
}
}
public class Character
{
public string Name { get; set; }
private ICanFly _flyAbility;
private ICanSwim _swimAbility;
private ICanCastSpells _spellAbility;
public Character(string name)
{
Name = name;
}
public void SetFlyAbility(ICanFly ability)
{
_flyAbility = ability;
}
public void SetSwimAbility(ICanSwim ability)
{
_swimAbility = ability;
}
public void SetSpellAbility(ICanCastSpells ability)
{
_spellAbility = ability;
}
public void PerformFly()
{
_flyAbility?.Fly();
}
public void PerformSwim()
{
_swimAbility?.Swim();
}
public void PerformSpell()
{
_spellAbility?.CastSpell();
}
}
class Program
{
static void Main()
{
// Ein fliegender Magier - ohne eigene Klasse!
var mage = new Character("Gandalf");
mage.SetFlyAbility(new FlyBehavior());
mage.SetSpellAbility(new SpellBehavior());
mage.PerformFly(); // Ausgabe: Hebt ab!
mage.PerformSpell(); // Ausgabe: Zaubert Feuerball!
}
}Du brauchst jetzt keine `FlyingMage`-Klasse mehr. Du fügst die Verhalten (Behaviors) einfach per Komposition hinzu. Dieses Vorgehen ist ein bekanntes Entwurfsmuster: das Strategy Pattern (Strategie-Muster).
Welche Fehler solltest du bei der Objektmodellierung vermeiden?
Fehler 1: Vererbung für Code-Wiederverwendung missbrauchen
Viele Anfänger erben nur, um sich Tipparbeit zu sparen - auch wenn gar keine ist-ein-Beziehung vorliegt.
// Falsch: Ein Auto ist kein Motor!
public class Engine
{
public void Start() { }
}
public class Car : Engine // Logisch falsch!
{
}// Richtig: Ein Auto hat einen Motor (Komposition)
public class Car
{
private Engine _engine = new Engine();
public void StartCar()
{
_engine.Start();
}
}Fehler 2: Tiefe Vererbungshierarchien aufbauen
Drei oder vier Ebenen Vererbung (z.B. `Vehicle` -> `LandVehicle` -> `Car` -> `SportsCar`) werden schnell unübersichtlich. Eine kleine Änderung ganz oben betrifft alle Klassen darunter. Halte Vererbungshierarchien flach - maximal zwei Ebenen sind ein gutes Ziel.
Fehler 3: sealed vergessen
Wenn eine Klasse nicht vererbt werden soll, markiere sie mit `sealed`. Das verhindert, dass andere Entwickler (oder du selbst in drei Monaten) von einer Klasse erben, die dafür gar nicht gedacht war. Details dazu findest du im Microsoft Learn-Artikel über sealed.
Übungstipp für Azubis und Studenten
Nimm dir 30 Minuten Zeit und implementiere ein kleines Tier-System. Versuche es zuerst mit Vererbung - dann mit Komposition.
Anforderungen:
Einige Tiere können fliegen.
Einige können schwimmen.
Einige können beides.
Manche können keines von beiden.
Du wirst schnell merken, dass die Kompositionslösung viel sauberer und leichter zu erweitern ist. Speichere das Projekt - es ist ein hervorragendes Code-Beispiel für deine Bewerbungsmappe.
FAQ: Häufige Fragen zu C# Komposition Vererbung
Ist Komposition immer besser als Vererbung?
Nein. Bei echter Subtyping-Beziehung (wenn Polymorphie nötig ist) ist Vererbung oft sauberer und verständlicher. Komposition glänzt bei flexibler Verhaltens-Kombination.
Was bedeutet "Favor Composition over Inheritance"?
Das ist ein Entwurfsprinzip aus dem Klassiker "Design Patterns" der Gang of Four (Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides). Es besagt: Bevorzuge Komposition, weil sie flexibler und robuster gegenüber späten Änderungen ist.
Kann ich Komposition und Vererbung kombinieren?
Ja, absolut! Das ist in der Praxis sogar der Normalfall. Eine `List<T>` in C# nutzt intern Komposition (sie enthält ein Array), implementiert aber gleichzeitig `IList<T>` (Interface-Vererbung).
Was ist der Unterschied zwischen Komposition und Aggregation?
Bei der Komposition ist das Teil untrennbar mit dem Ganzen verbunden (das Herz stirbt mit dem Menschen). Bei der Aggregation können Teile unabhängig existieren (ein Spieler kann das Team verlassen).
Warum gibt es keine Mehrfachvererbung bei Klassen in C#?
C# verbietet Mehrfachvererbung bei Klassen, um das sogenannte Diamond Problem zu vermeiden. Dieses entsteht, wenn zwei Basisklassen dieselbe Methode unterschiedlich implementieren. Mit Komposition und Interfaces hast du dieses Problem nicht.
Fazit
Vererbung ist mächtig, aber starr. Komposition ist flexibler und hält deinen Code lose gekoppelt (loose coupling). Die Faustregel für das Thema C# Komposition Vererbung lautet: Nutze Vererbung für echte "ist-ein"-Beziehungen mit Polymorphie. Nutze Komposition, wenn du Verhalten flexibel kombinieren willst.
Wenn du dieses Prinzip verstanden hast, öffnen sich dir viele fortgeschrittene Entwurfsmuster wie Strategy, Decorator oder State. Unser Beitrag zum UML-Klassendiagramm in C# hilft dir übrigens, diese Beziehungen grafisch darzustellen.
Brauchst du Unterstützung bei C#, objektorientierter Programmierung oder anderen IT-Themen? Bei study-it.education findest du erfahrene Nachhilfelehrer für Azubis, Studenten und Berufseinsteiger. Schau vorbei und vereinbare eine kostenlose Probestunde!
1:1-Hilfe zu diesem Thema?
Brauchst du jemand, der das mit dir durchgeht?
Statt nochmal lesen: 30 min mit einem Senior-Dev.
Kostenloses Erstgespräch buchen →
Vererbung oder Komposition in C#? Dieser Artikel erklärt den Unterschied und zeigt, wann welche Methode für dein Projekt die bessere Wahl ist.
marcel.schmidtpeter@study-it.education →Mehr Lesestoff
C# LINQ filtern und transformieren: Einfach erklärt mit Beispielen
LINQ macht Datenfilterung in C# kinderleicht: Mit Where, Select & Co. filterst und transformierst du Listen in wenigen Zeilen – hier lernst du wie!
C# Nullable einfach erklärt: So vermeidest du NullReferenceExceptions
Nullable-Typen in C# markieren Variablen, die null sein dürfen – und helfen dir, NullReferenceExceptions früh zu erkennen und zu vermeiden.
C# Lambda Expression einfach erklärt: Syntax & Beispiele
Lambda-Ausdrücke in C# verständlich erklärt: Syntax, Func & Action sowie praxisnahe Beispiele für Azubis, Studenten und Berufseinsteiger.