339 lines
5.5 KiB
Markdown
339 lines
5.5 KiB
Markdown
|
|
# Vererbung, Überschreiben und Polymorphie in C#
|
||
|
|
|
||
|
|
## Ziel dieser Einheit
|
||
|
|
|
||
|
|
In dieser Einheit lernst du:
|
||
|
|
|
||
|
|
- was abstrakte Klassen sind
|
||
|
|
- wie Vererbung in C# funktioniert
|
||
|
|
- was der Unterschied zwischen `override` und `new` ist
|
||
|
|
- wie Polymorphie funktioniert
|
||
|
|
- warum Casting notwendig sein kann
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 1. Grundidee: Vererbung
|
||
|
|
|
||
|
|
Definition:
|
||
|
|
|
||
|
|
Klassen können von anderen Klassen erben.
|
||
|
|
Dabei übernehmen sie Eigenschaften und Methoden.
|
||
|
|
|
||
|
|
Begriffe:
|
||
|
|
- Basisklasse (Elternklasse)
|
||
|
|
- Subklasse (Kindklasse)
|
||
|
|
- Vererbung
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 2. Die Basisklasse: Krokodil
|
||
|
|
|
||
|
|
public abstract class Krokodil
|
||
|
|
|
||
|
|
Erläuterung:
|
||
|
|
|
||
|
|
- abstrakte Klasse → kann nicht instanziiert werden
|
||
|
|
- dient als gemeinsame Grundlage
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Property
|
||
|
|
|
||
|
|
public string Farbe { get; private set; }
|
||
|
|
|
||
|
|
- Property mit unsichtbarem Backing-Field
|
||
|
|
- Setter ist privat
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Konstruktoren
|
||
|
|
|
||
|
|
protected Krokodil() : this("Keine Farbe")
|
||
|
|
|
||
|
|
- Konstruktor-Verkettung mit `this`
|
||
|
|
|
||
|
|
protected Krokodil(string farbe)
|
||
|
|
{
|
||
|
|
Farbe = farbe;
|
||
|
|
KrokodilListe.Add(this);
|
||
|
|
}
|
||
|
|
|
||
|
|
- jedes Objekt wird automatisch in eine Liste eingefügt
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Abstrakte Methode
|
||
|
|
|
||
|
|
public abstract void ZeigeInfoZumLebensraum();
|
||
|
|
|
||
|
|
Erläuterung:
|
||
|
|
|
||
|
|
- muss in allen Unterklassen implementiert werden
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Virtuelle Methode
|
||
|
|
|
||
|
|
public virtual void Schwimmen()
|
||
|
|
{
|
||
|
|
Console.WriteLine("Ich schwimme im Wasser.");
|
||
|
|
}
|
||
|
|
|
||
|
|
Erläuterung:
|
||
|
|
|
||
|
|
- kann überschrieben werden
|
||
|
|
- muss aber nicht
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3. Klasse Leistenkrokodil
|
||
|
|
|
||
|
|
public sealed class Leistenkrokodil : Krokodil
|
||
|
|
|
||
|
|
Erläuterung:
|
||
|
|
|
||
|
|
- `sealed` → keine weitere Vererbung möglich
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Überschreiben abstrakter Methoden
|
||
|
|
|
||
|
|
public override void ZeigeInfoZumLebensraum()
|
||
|
|
|
||
|
|
Erläuterung:
|
||
|
|
|
||
|
|
- `override` ist verpflichtend
|
||
|
|
- Verhalten wird neu definiert
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Überschreiben virtueller Methoden
|
||
|
|
|
||
|
|
public override void Schwimmen()
|
||
|
|
{
|
||
|
|
base.Schwimmen();
|
||
|
|
Console.WriteLine("Ich schwimme im Salzwasser.");
|
||
|
|
}
|
||
|
|
|
||
|
|
Erläuterung:
|
||
|
|
|
||
|
|
- `base` greift auf Verhalten der Basisklasse zu
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Eigene Methode
|
||
|
|
|
||
|
|
public void ImSchlammLiegen()
|
||
|
|
|
||
|
|
- nur in dieser Klasse verfügbar
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 4. Klasse Nilkrokodil
|
||
|
|
|
||
|
|
public class Nilkrokodil : Krokodil
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Überschreiben mit sealed
|
||
|
|
|
||
|
|
public sealed override void ZeigeInfoZumLebensraum()
|
||
|
|
|
||
|
|
- verhindert weiteres Überschreiben
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Methode mit new
|
||
|
|
|
||
|
|
public new void Schwimmen()
|
||
|
|
|
||
|
|
Erläuterung:
|
||
|
|
|
||
|
|
- `new` blendet die Methode aus
|
||
|
|
- kein echtes Überschreiben
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Eigene Methode
|
||
|
|
|
||
|
|
public void ImGrasLiegen()
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Property mit new
|
||
|
|
|
||
|
|
public new string Farbe => base.Farbe.ToUpper();
|
||
|
|
|
||
|
|
Erläuterung:
|
||
|
|
|
||
|
|
- Getter wurde neu definiert
|
||
|
|
- gibt Wert in Großbuchstaben zurück
|
||
|
|
- Expression Bodied Member
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 5. Anwendung in der Main-Methode
|
||
|
|
|
||
|
|
Leistenkrokodil leistenkrokodil = new Leistenkrokodil("...");
|
||
|
|
|
||
|
|
Console.WriteLine($"Farbe des Krokodils: {leistenkrokodil.Farbe}");
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Methodenaufrufe
|
||
|
|
|
||
|
|
leistenkrokodil.ZeigeInfoZumLebensraum();
|
||
|
|
leistenkrokodil.Schwimmen();
|
||
|
|
leistenkrokodil.ImSchlammLiegen();
|
||
|
|
|
||
|
|
- implementierte Methode
|
||
|
|
- überschriebene Methode
|
||
|
|
- eigene Methode
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Nilkrokodil
|
||
|
|
|
||
|
|
Nilkrokodil nilkrokodil = new Nilkrokodil("...");
|
||
|
|
|
||
|
|
Console.WriteLine($"Farbe des Krokodils: {nilkrokodil.Farbe}");
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Verhalten von new
|
||
|
|
|
||
|
|
nilkrokodil.Schwimmen();
|
||
|
|
|
||
|
|
- kein Unterschied sichtbar bei direkter Verwendung
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 6. Polymorphie mit Basisklasse
|
||
|
|
|
||
|
|
foreach (Krokodil k in Krokodil.KrokodilListe)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Reflection
|
||
|
|
|
||
|
|
Console.WriteLine(k.GetType().Name);
|
||
|
|
|
||
|
|
- tatsächlicher Typ zur Laufzeit
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Verhalten von override
|
||
|
|
|
||
|
|
k.ZeigeInfoZumLebensraum();
|
||
|
|
|
||
|
|
- abhängig von der Subklasse
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Verhalten von new
|
||
|
|
|
||
|
|
Console.WriteLine(k.Farbe);
|
||
|
|
|
||
|
|
Erläuterung:
|
||
|
|
|
||
|
|
- nur Basisklassen-Version wird verwendet
|
||
|
|
- `new` greift hier nicht
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Unterschied sichtbar machen
|
||
|
|
|
||
|
|
k.Schwimmen();
|
||
|
|
|
||
|
|
- einmal überschrieben
|
||
|
|
- einmal nur ausgeblendet
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 7. Casting
|
||
|
|
|
||
|
|
### Direktes Casting
|
||
|
|
|
||
|
|
((Leistenkrokodil)k).ImSchlammLiegen();
|
||
|
|
|
||
|
|
- kann Exception werfen
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Sicheres Casting mit as
|
||
|
|
|
||
|
|
(k as Nilkrokodil)?.ImGrasLiegen();
|
||
|
|
|
||
|
|
- gibt null zurück
|
||
|
|
- `?` prüft auf null
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Casting mit is
|
||
|
|
|
||
|
|
if (k is Leistenkrokodil l)
|
||
|
|
l.ImSchlammLiegen();
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
if (k is Nilkrokodil n)
|
||
|
|
{
|
||
|
|
n.ImGrasLiegen();
|
||
|
|
n.Schwimmen();
|
||
|
|
}
|
||
|
|
|
||
|
|
- kombiniert Typprüfung und Casting
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 8. Wichtige Konzepte im Überblick
|
||
|
|
|
||
|
|
### abstract
|
||
|
|
- MUSS überschrieben werden
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### virtual
|
||
|
|
- KANN überschrieben werden
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### override
|
||
|
|
- echtes Überschreiben
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### new
|
||
|
|
- nur Ausblenden
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### sealed
|
||
|
|
- verhindert weiteres Überschreiben
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Polymorphie
|
||
|
|
- Verhalten abhängig vom tatsächlichen Objekttyp
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Zusammenfassung
|
||
|
|
|
||
|
|
- Vererbung ermöglicht Wiederverwendung von Code
|
||
|
|
- abstrakte Methoden müssen implementiert werden
|
||
|
|
- virtuelle Methoden können überschrieben werden
|
||
|
|
- `override` und `new` verhalten sich unterschiedlich
|
||
|
|
- Polymorphie bestimmt das Verhalten zur Laufzeit
|
||
|
|
- Casting ist notwendig für Zugriff auf Subklassen
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Verständnisfragen
|
||
|
|
|
||
|
|
- Was ist der Unterschied zwischen `override` und `new`?
|
||
|
|
- Wann wird eine Methode überschrieben?
|
||
|
|
- Warum funktioniert `new` bei Polymorphie anders?
|
||
|
|
- Wann ist Casting notwendig?
|
||
|
|
- Was macht `sealed`?
|
||
|
|
``
|