Tag 3 Unterricht und Aufgaben
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace _10_Override.Krokodile;
|
||||
|
||||
public abstract class Krokodil
|
||||
{
|
||||
public static readonly List<Krokodil> KrokodilListe = new List<Krokodil>();
|
||||
|
||||
/*
|
||||
// Full-Property mit sichtbarem Backing-Field:
|
||||
private string farbe;
|
||||
|
||||
public string Farbe
|
||||
{
|
||||
get => farbe; // Expression-Bodied
|
||||
|
||||
private set
|
||||
{
|
||||
farbe = value;
|
||||
}
|
||||
}*/
|
||||
|
||||
public string Farbe { get; private set; } // Property mit unsichtbarem Backing-Field.
|
||||
// Das passende Feld zur Property wird vom Compiler angelegt und wir haben im Code keinen direkten Zugriff darauf.
|
||||
|
||||
// Abstrakte Klassen haben in der Regel 'protected' Konstruktoren.
|
||||
protected Krokodil() : this("Keine Farbe") // Konstruktor-Verkettung mit 'this'.
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected Krokodil(string farbe)
|
||||
{
|
||||
Farbe = farbe;
|
||||
KrokodilListe.Add(this);
|
||||
}
|
||||
|
||||
// Abstrakte Methode:
|
||||
/// <summary>
|
||||
/// Diese Methode gibt Informationen zum Lebensraum des Krokodils aus.
|
||||
/// </summary>
|
||||
public abstract void ZeigeInfoZumLebensraum();
|
||||
|
||||
// 'virtual-Methoden KÖNNEN überschrieben werden. 'abstract'-Methoden MÜSSEN überschrieben werden. Methoden, die nicht abstract oder virtual sind, können NICHT überschrieben werden.
|
||||
public virtual void Schwimmen()
|
||||
{
|
||||
Console.WriteLine("Ich schwimme im Wasser.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
|
||||
namespace _10_Override.Krokodile;
|
||||
|
||||
// 'sealed': Entspricht in diesem Kontext dem 'final' aus Java. Die Klasse wird versiegelt und es kann nicht weiter von ihr geerbt werden.
|
||||
public sealed class Leistenkrokodil : Krokodil
|
||||
{
|
||||
public Leistenkrokodil(string farbe) : base(farbe)
|
||||
{
|
||||
}
|
||||
|
||||
// Abstrakte Methoden MÜSSEN in nicht-abstrakten Klassen überschrieben werden.
|
||||
// Unterschied zu Java: 'override' ist ein Schlüsselwort, welches wir zum Überschreiben angeben MÜSSEN.
|
||||
public override void ZeigeInfoZumLebensraum()
|
||||
{
|
||||
Console.WriteLine("Ich lebe in Ostindien, Südostasien und komme sogar bis nach Nordaustralien.");
|
||||
}
|
||||
|
||||
// Virtuelle Methoden KÖNNEN überschrieben werden:
|
||||
public override void Schwimmen()
|
||||
{
|
||||
base.Schwimmen(); // Mit 'base' können wir hier das Verhalten der überschriebenen Methode wiederverwenden.
|
||||
Console.WriteLine("Ich schwimme im Salzwasser.");
|
||||
}
|
||||
|
||||
// Diese Methode wird nicht geerbt oder überschrieben. Sie ist nur in dieser Klasse vorhanden.
|
||||
public void ImSchlammLiegen()
|
||||
{
|
||||
Console.WriteLine("Ich liege im Schlamm. Hier mag ich es.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
|
||||
namespace _10_Override.Krokodile;
|
||||
|
||||
public class Nilkrokodil : Krokodil
|
||||
{
|
||||
public Nilkrokodil(string farbe) : base(farbe)
|
||||
{
|
||||
}
|
||||
|
||||
public sealed override void ZeigeInfoZumLebensraum() // 'sealed' kann für Methoden verwendet werden, um weiteres Überschreiben zu verbieten.
|
||||
{
|
||||
Console.WriteLine("Anders als mein Name vermuten lässt, lebe ich nicht nur am Nil, sondern in fast ganz Afrika.");
|
||||
}
|
||||
|
||||
// 'new' kann verwendet werden, um den geerbten Member auszublenden. Dies wird vor allem für Methoden verwendet, die weder virtual noch abstract sind. In C# können nur Methoden überschrieben werden, die die Schlüsselwörter 'virtual', 'abstract' oder 'override' verwenden. 'new' funktioniert auch dort, wo 'override' nicht funktionieren würde.
|
||||
public new void Schwimmen()
|
||||
{
|
||||
base.Schwimmen();
|
||||
Console.WriteLine("Ich schwimme im Süßwasser.");
|
||||
}
|
||||
|
||||
public void ImGrasLiegen()
|
||||
{
|
||||
Console.WriteLine("Ich liege im Gras. Hier mag ich es.");
|
||||
}
|
||||
|
||||
// Wir können in C# nur abstrakte und virtuelle Methoden überschreiben. Um trotzdem das Verhalten einer nicht-abstrakten und nicht-virtuellen Methode verändern zu können, gibt es in C# noch das 'new'-Schlüsselwort.
|
||||
public new string Farbe => base.Farbe.ToUpper(); // Der Getter der Property wurde neu definiert und gibt nun die Farbe in Großbuchstaben zurück.
|
||||
// Diese Schreibweise hier wird "Expression Bodied Member" genannt und funktioniert bei allen Methoden und Properties, die nur 1 Befehl ausführen.
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using _10_Override.Krokodile;
|
||||
|
||||
namespace _10_Override;
|
||||
|
||||
public class Override
|
||||
{
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
Leistenkrokodil leistenkrokodil = new Leistenkrokodil("Grau bis graubraun oder goldbraun");
|
||||
Console.WriteLine($"Farbe des Krokodils: {leistenkrokodil.Farbe}"); // Mit dem '$' vor der Zeichenkette machen wir eine "String-Interpolation". Das heißt, wir können Variablen in { } direkt in die Zeichenkette schreiben.
|
||||
leistenkrokodil.ZeigeInfoZumLebensraum(); // die abstrakte Methode, die in der Subklasse durch Überschreiben implementiert wurde.
|
||||
leistenkrokodil.Schwimmen(); // Virtuelle Methode, die überschrieben wurde.
|
||||
leistenkrokodil.ImSchlammLiegen(); // Eine in der Subklasse erstellte Methode.
|
||||
|
||||
Nilkrokodil nilkrokodil = new Nilkrokodil("Oberseits dunkel-olivfarben, der Bauch ist einheitlich porzellanfarben");
|
||||
Console.WriteLine($"Farbe des Krokodils: {nilkrokodil.Farbe}"); // Beispiel zu 'new' -> Wir bekommen alles in Großbuchstaben.
|
||||
nilkrokodil.ZeigeInfoZumLebensraum();
|
||||
nilkrokodil.Schwimmen(); // Beispiel zu 'new' -> Es ist hier noch kein Unterschied zum Override sichtbar.
|
||||
nilkrokodil.ImGrasLiegen();
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Ausgabe aller Elemente der Krokodil-Liste:");
|
||||
foreach (Krokodil k in Krokodil.KrokodilListe)
|
||||
{
|
||||
Console.WriteLine(k.GetType().Name); // Mit "Reflection" den Namen des instanziierten Datentyps abfragen.
|
||||
Console.WriteLine(k.Farbe); // Hier greift 'new' nicht, da der Typ die Basisklasse ist. In diesem Fall würde nur 'override' funktionieren.
|
||||
|
||||
k.ZeigeInfoZumLebensraum();
|
||||
// Da diese Methode in der Basisklasse definiert ist, verfügen auch alle Subklassen darüber.
|
||||
// Die Methode wird aber je nach Subklasse ein anderes Verhalten zeigen, da sie dort überschrieben wurde.
|
||||
|
||||
k.Schwimmen(); // Diese Methode haben wir einmal überschrieben und einmal nur ausgeblendet. Daher werden wir einmal die Ausgabe aus der überschreibenden Variante sehen und einmal die Ausgabe aus der Basisklasse.
|
||||
|
||||
// Möchte ich Member aufrufen, die es nur in den Subklassen gibt, muss konvertiert (gecastet) werden:
|
||||
//((Leistenkrokodil)k).ImSchlammLiegen(); // Verursacht eine Exception, wenn nicht gecastet werden kann.
|
||||
//(k as Nilkrokodil)?.ImGrasLiegen(); // 'as' gibt Null zurück, wenn nicht gecastet werden kann. '?' prüft auf Null.
|
||||
|
||||
// Mit 'is' prüfen wir, ob das Krokodil ein Leistenkrokodil ist. Wenn ja, wird gecastet und das Ergebnis 'l' zugewiesen:
|
||||
if (k is Leistenkrokodil l)
|
||||
l.ImSchlammLiegen();
|
||||
|
||||
// Mit 'is' prüfen wir, ob das Krokodil ein Nilkrokodil ist. Wenn ja, wird gecastet und das Ergebnis 'n' zugewiesen:
|
||||
if (k is Nilkrokodil n)
|
||||
{
|
||||
n.ImGrasLiegen();
|
||||
n.Schwimmen(); // Nach dem Cast wird der Typ der Subklasse verwendet und wir sehen die Ausgabe aus der 'new'-Methode.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user