CS_LEVEL_3_SOLUTION - OnlyCook/abitur-elite-code GitHub Wiki
Level 3 – Musterlösung: Abstrakte Klassen und Vererbung
Lösung
public abstract class Tier
{
protected string name;
public Tier(string name)
{
this.name = name;
}
}
public class Loewe : Tier
{
private int laenge;
public Loewe(string name, int laenge) : base(name)
{
this.laenge = laenge;
}
public string Bruellen()
{
return "ROAR!!!";
}
}
Erklärung
Abstrakte Klassen
Eine abstrakte Klasse ist eine Klasse, von der man keine direkten Objekte erstellen kann. Sie dient ausschließlich als Vorlage (Basisklasse) für andere Klassen, die von ihr erben.
public abstract class Tier { ... }
Das bedeutet: new Tier(...) würde einen Compilerfehler erzeugen. Man kann aber sehr wohl new Loewe(...) schreiben, weil Loewe eine konkrete (nicht abstrakte) Klasse ist.
Warum abstrakt? Im echten Zoo gibt es kein Tier, das einfach nur „Tier" ist – es ist immer ein Löwe, ein Elefant, usw. Abstrakte Klassen bilden genau das ab: das Konzept existiert, aber nie ohne eine konkrete Ausprägung.
In Java und C# ist die Syntax für abstrakte Klassen identisch: abstract class.
Der protected-Zugriffsmodifikator
Bisher kennen wir private (nur innerhalb der Klasse) und public (überall). Das Attribut name ist hier protected:
protected string name;
| Modifikator | Zugriff von der eigenen Klasse | Zugriff von Unterklassen | Zugriff von außen |
|---|---|---|---|
private |
✅ | ❌ | ❌ |
protected |
✅ | ✅ | ❌ |
public |
✅ | ✅ | ✅ |
Im UML-Diagramm wird protected mit einem # gekennzeichnet. protected macht Sinn, wenn Unterklassen das Attribut kennen und damit arbeiten sollen, es aber trotzdem nicht frei zugänglich sein soll.
Vererbung mit :
Vererbung bedeutet: Eine Klasse übernimmt alle Attribute und Methoden einer anderen Klasse und kann sie erweitern.
public class Loewe : Tier { ... }
Der Doppelpunkt : ist die C#-Syntax für Vererbung. In Java würde man stattdessen extends schreiben:
| Java | C# |
|---|---|
class Loewe extends Tier |
class Loewe : Tier |
Loewe ist die Unterklasse (auch: abgeleitete Klasse), Tier ist die Oberklasse (auch: Basisklasse). Loewe erbt name von Tier – es muss also nicht nochmal deklariert werden.
Der Basis-Konstruktor mit base
Wenn eine Unterklasse einen Konstruktor hat, muss sie sich auch darum kümmern, dass der Konstruktor der Oberklasse aufgerufen wird. Das geschieht mit : base(...) direkt hinter dem Konstruktor-Kopf:
public Loewe(string name, int laenge) : base(name)
{
this.laenge = laenge;
}
Hier passiert folgendes der Reihe nach:
Loeweempfängtnameundlaengeals Parameter.: base(name)ruft den Konstruktor vonTierauf und übergibtname–Tiersetzt damitthis.name.- Danach wird
this.laenge = laengeim Körper vonLoeweausgeführt.
Loewe selbst muss name also nicht nochmal zuweisen – das erledigt die Oberklasse. laenge hingegen ist nur in Loewe bekannt, also wird es hier gesetzt.
In Java heißt das Äquivalent
super(name)– die Logik ist identisch, nur die Schlüsselwörter unterscheiden sich.
| Java | C# |
|---|---|
super(name) |
base(name) |
Die Methode Bruellen()
public string Bruellen()
{
return "ROAR!!!";
}
Das ist eine ganz normale Methode in Loewe. Sie gibt einen string zurück – der konkrete Inhalt ist frei wählbar, solange der Rückgabetyp stimmt. Da Tier diese Methode nicht kennt, gehört sie ausschließlich zur Klasse Loewe.
Das Gesamtbild
Tier (abstract)
├── protected string name
└── public Tier(name)
↑ erbt von / base(name)
Loewe
├── private int laenge
├── public Loewe(name, laenge)
└── public string Bruellen()
Loewe ist eine Spezialisierung von Tier: Es bringt alles mit, was Tier definiert, und ergänzt darüber hinaus eigene Attribute und Methoden.