Почему виртуальная функция Grand parent вызывается в C#

#c# #oop

#c# #ооп

Вопрос:

У меня есть следующий код. Кто-нибудь может ответить, почему вызывается метод base-show, а не метод derive-show в этом случае. Как в этом случае будет выделяться память для функций show производного и базового классов.

 class OverrideAndNew : Derive
{

    public static void Main()
    {
        Derive obj = new Derive1();
        obj.Show();

        Console.ReadLine();
    }
}

class Base
{
    public virtual void Show()
    {
        Console.WriteLine("Base - Show");
    }
}

class Derive : Base
{
    protected virtual void Show()
    {
        Console.WriteLine("Derive - Show");
    }
}

class Derive1 : Derive
{
    protected override void Show()
    {
        Console.WriteLine("Derive1 - Show");
    }
}
  

Ответ №1:

Потому что вы ее вызвали. Вы не можете изменять модификаторы доступа при переопределении метода. Итак, по сути, Derive1 переопределил Show метод Derive . Но функция derive никогда не переопределяла функцию Base. Итак, существует только один общедоступный метод Show, реализованный в Base.

То, что вы, вероятно, хотели сделать, было:

 class OverrideAndNew
{
    public static void Main()
    {
        Derive obj = new Derive1();
        obj.Show();

        Console.ReadLine();
    }
}

class Base
{
    public virtual void Show()
    {
        Console.WriteLine("Base - Show");
    }
}

class Derive : Base
{
    public override void Show()
    {
        Console.WriteLine("Derive - Show");
    }
}

class Derive1 : Derive
{
    public override void Show()
    {
        Console.WriteLine("Derive1 - Show");
    }
}
  

Обратите внимание, что сигнатура метода остается неизменной. Она всегда общедоступна, потому что Base сказал, что она должна быть общедоступной. Это всегда одно и то же имя, возвращаемый тип и параметры (в данном случае их нет).

Комментарии:

1. Просто чтобы добавить к ответу nvoigt из документации MSDN по защищенному модификатору «Защищенное ключевое слово является модификатором доступа участника. Защищенный элемент доступен внутри своего класса и экземплярами производного класса.». Следовательно, вызывая метод объекта, вы получаете доступ к общедоступному методу (т.Е. Base).

Ответ №2:

Ваш защищенный метод не переопределяет Base.Show , он просто скрывает его. Вам нужно объявить Show в Derive с тем же модификатором доступа (т. Е. public) и использовать override ключевое слово, чтобы явно объявить, что вы намерены переопределить метод.

Обратите внимание, что эта программа выдает предупреждение компилятора, в котором говорится следующее:

‘Производная.Show()’ скрывает унаследованный элемент ‘Base.Show()’. Чтобы заставить текущий элемент переопределять эту реализацию, добавьте ключевое слово override. В противном случае добавьте ключевое слово new.

Отдельный вопрос заключается в том, почему это всего лишь предупреждение, а не ошибка. Это потому, что C # разработан для минимизации так называемой проблемы хрупкости базового класса. Если Base она находится в одной сборке, а Derive — в другой (возможно, созданной разными командами или даже разными компаниями), то с точки зрения автора Derive было бы нежелательно, если бы версия 2 Base добавила новый метод Show , который нарушил существующий код в Derive . Следовательно, это всего лишь предупреждение, а не ошибка.