Зачем мне нужно объявлять виртуальный метод, когда я могу скрыть его в производном классе

#c# #.net #oop #inheritance #virtual

#c# #.net #ооп #наследование #виртуальный

Вопрос:

 class clsTestParent
    {
       public void testNoAbstract()
        {
            Console.WriteLine("Parent Method Call");
        }
    }

    class clsDerivedTest : clsTestParent
    {
     public void testNoAbstract()
        {
            Console.WriteLine("Child Method Hiding Parent Method");
        }
    }

            clsTestParent objParent = new clsTestParent();
            clsTestParent objOfParentFromDerived = new clsDerivedTest();
            clsDerivedTest objDerived = new clsDerivedTest();

            objParent.testNoAbstract();
            objOfParentFromDerived.testNoAbstract();
            objDerived.testNoAbstract();
  

Вывод:
Вызов родительского метода
Вызов родительского метода
Дочерний метод, скрывающий родительский метод

Но когда я объявляю testNoAbstract() как виртуальный и перезаписываю в производном классе, вывод будет таким, как показано ниже:

 Parent Method Call  
Child Method Hiding Parent Method
Child Method Hiding Parent Method
  

Раньше я думал, что мы можем переопределить метод в производном классе, только если он определен как abstract или virtual , но, как теперь видно, мы можем скрыть метод родительского класса, просто переопределив его в производном классе.

Хотя я вижу разницу в выходных данных путем изменения кода, я хотел бы знать, в чем различия между двумя вышеупомянутыми методами и почему это приводит к разным результатам.

Ответ №1:

Если вы когда-нибудь это сделаете clsTestParent a = new clsDerivedTest () — вы никогда не сможете выполнить тот, что находится в классе clsDerivedTest !!!!

В этом разница, и именно поэтому компилятор предупреждает вас.

вы действительно сделаете это, если хотите предварительно сформировать архитектуру полиморфизма.

Microsoft говорит вам: «Послушайте, вы создали класс, и мы предоставим вам все общедоступные вещи и т.д., Но мы не знаем, как вы хотите реализовать методы… если вы будете использовать virtual override — вы сможете выполнить другой метод с помощью типа instace. и если вы не будете переопределять — так что функция отца всегда будет выполняться …. это ваш выбор… мы предупреждаем вас «… и они предупреждают

Ответ №2:

Вот почему «переопределение» — несколько неподходящее слово для этого. Виртуальный вызов разрешает ваш тип во время выполнения, вот почему вы смогли:

     clsTestParent objOfParentFromDerived = new clsDerivedTest();
    objOfParentFromDerived.testAbstractOrVirtual(); // marked as virtual or abstract in base class
  

и вызов был разрешен во время выполнения, для метода, определенного в классе, который objOfParentFromDerived действительно является ( new operator — clsDerivedTest ), а не для метода, определенного в классе, с помощью которого он был объявлен( clsTestParent ).

Если он не помечен ни virtual , ни abstract тогда компилятор предупреждает вас, потому что вызов будет разрешен на основе типа, с которым была объявлена переменная.