Сегодня, выполняя некоторые тестовые классы в C#, я наткнулся на некоторые вопросы относительно наследования (и интерфейсов) в C#. Ниже приведен пример кода для иллюстрации моих вопросов.Неожиданное поведение наследования и интерфейсов в 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();
}
}
Вот мои вопросы:
- объявление и инициализация с Flugzeug FLG = новый Motorflugzeug(); (case2) Я ожидал, что Motorflugzeug.Starten вызывается вместо Flugzeug.Starten (и я уверен, что это поведение Java-шоу). openbook.galileo говорит, что в этом случае с использованием C# runtime-type - Flugzeug. Есть ли причина для этого? Для меня такое наследование не имеет смысла.
- То же самое с ILuftfahrzeug flg = new Motorflugzeug(); (case3) - здесь я мог бы обойтись, позволив Motorflugzeug явно реализовать ILuftfahrzeug (как в примере кода). Но для меня это лишнее, так как Flugzeug уже реализует ILuftfahrzeug.
- Теперь я хочу перезаписать защищенные методы Dings(), которые вызывается Starten(). Если я запустил код, как он реализован в примере, все работает отлично. Но если Starten() не реализован в Motorflugzeug, вместо Motorflugzeug.Dings() будет вызываться Dings() базового слоя. Мне сказали, что Java также показывает это поведение.
Есть ли какой-нибудь шаблон, чтобы обойти это? В противном случае мне пришлось бы перезаписать каждый метод (здесь: Starten()), который вызывает метод, который я на самом деле намерен перезаписать (здесь: Dings()), даже если он точно такой же, как в базовом классе.