List<Tier> tiere = [new Hund("Rex"), new Katze("Mimi"), new Tier("Etwas")];
foreach (var t in tiere) Console.WriteLine(t.Vorstellen()); // Polymorphie
class Tier
{
public string Name { get; }
public Tier(string name) => Name = name;
public virtual string Laut() => "..."; // virtual: darf überschrieben werden
public string Vorstellen() => $"{Name} macht {Laut()}";
}
class Hund : Tier
{
public Hund(string name) : base(name) { } // Konstruktor der Basis
public override string Laut() => "Wuff";
}
class Katze : Tier
{
public Katze(string name) : base(name) { }
public override string Laut() => "Miau";
}Ausgabe
Rex macht Wuff Mimi macht Miau Etwas macht ...
class B : Aerbt vonA; eine Basisklasse, aber beliebig viele Interfacesvirtualerlaubt Überschreiben,overrideüberschreibt,baseruft die Basis aufsealedverbietet weitere Vererbung/Überschreiben- Alle Klassen erben von
object(ToString,Equals,GetHashCode)
Abstrakte Klassen
Form[] formen = [new Kreis(1), new Quadrat(3)];
foreach (var f in formen) Console.WriteLine(f.Info());
abstract class Form
{
public abstract double Flaeche(); // muss überschrieben werden
public string Info() => $"{GetType().Name} mit Fläche {Flaeche():F2}";
}
class Kreis(double r) : Form { public override double Flaeche() => Math.PI * r * r; }
class Quadrat(double a) : Form { public override double Flaeche() => a * a; }Ausgabe
Kreis mit Fläche 3.14 Quadrat mit Fläche 9.00
Interfaces
Ein Interface beschreibt einen Vertrag. Eine Klasse kann mehrere umsetzen:
var e = new ElektroAuto();
e.Laden(50);
IFahrbar f = e;
f.Fahren();
Console.WriteLine(f.Art());
IFahrbar rad = new Fahrrad();
rad.Fahren();
Console.WriteLine(rad.Art());
interface IFahrbar
{
void Fahren();
string Art() => "Fahrzeug"; // Standardimplementierung
}
interface IAufladbar { void Laden(int prozent); }
class ElektroAuto : IFahrbar, IAufladbar
{
private int _akku = 20;
public void Fahren() => Console.WriteLine($"surr, Akku {_akku}%");
public void Laden(int prozent) => _akku = Math.Min(100, _akku + prozent);
public string Art() => "Elektroauto";
}
class Fahrrad : IFahrbar { public void Fahren() => Console.WriteLine("tret tret"); }Ausgabe
surr, Akku 70% Elektroauto tret tret Fahrzeug
Namenskonvention: Interfaces beginnen mit I (IList, IDisposable, IComparable).
Wichtige eingebaute Interfaces
| Interface | Bedeutung |
|---|---|
IDisposable | Ressourcen freigeben (using) |
IEnumerable<T> | kann mit foreach durchlaufen werden |
IComparable<T> | hat eine natürliche Reihenfolge (Sort) |
IEquatable<T> | typsichere Gleichheit |
IComparer<T> | Vergleichsregel von außen |
ICloneable | kopierbar |
var l = new List<Version> { new(1, 10), new(1, 2), new(2, 0) };
l.Sort();
Console.WriteLine(string.Join(" < ", l));
class Version : IComparable<Version>
{
public int Major { get; }
public int Minor { get; }
public Version(int major, int minor) { Major = major; Minor = minor; }
public int CompareTo(Version? other) => other is null ? 1 : (Major, Minor).CompareTo((other.Major, other.Minor));
public override string ToString() => $"{Major}.{Minor}";
}Ausgabe
1.2 < 1.10 < 2.0
Komposition und Abhängigkeiten über Interfaces
Programmiere gegen Schnittstellen statt konkrete Klassen. So lassen sich Teile austauschen und testen:
var dienst = new BestellDienst(new KonsolenMailer());
dienst.Bestelle("Mia");
interface IMailer { void Sende(string an, string text); }
class KonsolenMailer : IMailer { public void Sende(string an, string text) => Console.WriteLine($"Mail an {an}: {text}"); }
class BestellDienst(IMailer mailer) // Abhängigkeit hereingegeben
{
public void Bestelle(string kunde) => mailer.Sende(kunde, "Danke für deine Bestellung");
}Ausgabe
Mail an Mia: Danke für deine Bestellung
Dieses Muster heißt Dependency Injection. ASP.NET Core bringt dafür einen eingebauten Container mit.
Merke
virtual/override/base/sealedsteuern Vererbung; eine Basisklasse, viele Interfacesabstractfür Vorlagen mit Pflicht-Methoden- Interfaces (
IName) beschreiben Verträge, auch mit Standardimplementierungen IComparable<T>,IEnumerable<T>,IDisposablesind die wichtigsten Standard-Interfaces- Abhängigkeiten über Interfaces hereingeben (Dependency Injection)
Aufgabe
Entwirf ein Interface IZahlung mit Betrag() und zwei Klassen. Summiere die Beträge einer gemischten Liste.