Tag 3 Unterricht und Aufgaben

This commit is contained in:
wbs
2026-08-12 14:15:13 +02:00
parent a969e3cdc7
commit 78ac1b3936
73 changed files with 2928 additions and 0 deletions
+50
View File
@@ -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.");
}
}
+31
View File
@@ -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.
}
+51
View File
@@ -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.
}
}
}
}