#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
тогда компилятор предупреждает вас, потому что вызов будет разрешен на основе типа, с которым была объявлена переменная.