Heute, während der Implementierung einiger Testklassen in C#, stürzte ich auf einige Fragen in Bezug auf Vererbung (und Schnittstellen) in C#. Im Folgenden habe ich einen Beispielcode, um meine Fragen zu veranschaulichen.Unerwartete Verhalten von Vererbung und Schnittstellen in C#
interface ILuftfahrzeug
{
void Starten();
}
class Flugzeug : ILuftfahrzeug
{
public void Starten()
{
Console.WriteLine("Das Flugzeug startet, "+Dings());
}
protected string Dings()
{
return "Flugzeug Dings";
}
}
class Motorflugzeug : Flugzeug, ILuftfahrzeug
{
public new void Starten()
{
Console.WriteLine("Das Motorflugzeug startet, "+Dings());
}
protected new string Dings()
{
return "Motorflugzeug Dings";
}
}
class InterfaceUndVererbung
{
static void Main(string[] args)
{
//Motorflugzeug flg = new Motorflugzeug(); // case1: returns "Das Motorflugzeug startet, Motorflugzeug Dings"
//Flugzeug flg = new Motorflugzeug(); // case2: returns "Das Flugzeug startet, Flugzeug Dings"
ILuftfahrzeug flg = new Motorflugzeug(); // case3: returns "Das Motorflugzeug startet, Motorflugzeug Dings"
// if Motorflugzeug implements ILuftfahrzeug explicitly,
// otherwise "Das Motorflugzeug startet, Motorflugzeug Dings"
flg.Starten();
Console.ReadLine();
}
}
Das sind meine Fragen:
- Deklarieren und Initialisieren mit Flugzeug flg = new Motorflugzeug(); (case2) Ich habe erwartet, dass Motorflugzeug.Starten statt Flugzeug.Starten aufgerufen wird (und ich bin mir ziemlich sicher, dass dies das Verhalten von Java ist). openbook.galileo sagt, dass in diesem Fall mit C# der Runtime-Typ Flugzeug ist. Gibt es einen Grund dafür? Ein solches Vererbungsverhalten macht für mich keinen Sinn.
- Gleiches mit ILuftfahrzeug flg = neues Motorflugzeug(); (case3) - hier könnte ich umgehen indem ich das Motorflugzeug explizit ILuftfahrzeug implementiere (wie es im Beispielcode ist). Aber für mich ist das überflüssig, da Flugzeug ILuftfahrzeug bereits implementiert.
- Jetzt möchte ich eine geschützte Methoden Dings(), die von Starten() aufgerufen wird überschreiben. Wenn ich den Code ausführe, wie es im Beispiel implementiert ist, funktioniert alles. Aber wenn Steigen() nicht in Motorflugzeug implementiert wird, wird Dings() der Basisklasse anstelle von Motorflugzeug.Dings() aufgerufen. Mir wurde gesagt, dass Java auch dieses Verhalten zeigt.
Gibt es ein Muster, um dies zu umgehen? Sonst müsste ich jede Methode überschreiben (hier: Starten()), die die Methode aufruft, die ich eigentlich überschreiben möchte (hier: Dings()), auch wenn sie genau so ist wie in der Basisklasse.