Чем отличается перекрытие от переопределения метода?
Ответ
Перекрытие (в ваших терминах) означает, что метод в производном классе скрывает метод с той же самой сигнатурой в базовом классе.
Поэтому в C# рекомендуется для методов производных классов, которые перекрывают методы базовых классов, использовать ключевое слово new. Если вы забудете это сделать, то компилятор вас предупредит, что вы скрываете одноименную функцию с той же сигнатурой в базовом классе.
Например,
class Base
{
public void Hello() { Console.WriteLine( "I'm the base class" ); }
}
class Derived : Base
{
public new void Hello() { Console.WriteLine( "I'm the derived class" ); }
}
В этом случае для ссылок на базовый класс Base всегда будет вызываться метод Hello базового класса, а для ссылок на производный класс будет вызываться метод Hello производного класса.
Например,
Base b = new Base();
b.Hello(); // I'm the base class
Derived d = new Derived();
d.Hello(); // I'm the derived class
b = d;
b.Hello(); // I'm the base class
Переопределение применяется к виртуальным функциям. В производном классе виртуальная функция переопределяется. Для этого в базовом классе функция должна быть определена с ключевым словом virtual (или abstract), а в производном классе для ее переопределения необходимо указывать другое ключевое слово override
Например,
class Base
{
public virtual void Hello() { Console.WriteLine( "I'm the base class" ); }
}
class Derived : Base
{
public override void Hello() { Console.WriteLine( "I'm the derived class" ); }
}
Различие с предыдущим примером состоит в том, что если ссылка базового класса указывает на объект производного класса, то в этом случае будет вызвана переопределенная функция производного класса.
Base b = new Base();
b.Hello(); // I'm the base class
Derived d = new Derived();
d.Hello(); // I'm the derived class
b = d;
b.Hello(); `// I'm the derived class`
То есть различие состоит в этих двух предложениях. В первом случае для перекрытия
b = d;
b.Hello(); // I'm the base class
^^^^^^^^^^^^^^^^^^
а во втором случае при переопределении имеем
b = d;
b.Hello(); `// I'm the derived class`
^^^^^^^^^^^^^^^^^^^^^^^^
То есть в первом случае мы в каждом новом производном классе в иерархии классов объявляем новую функцию, которая скрывает функцию с той же сигнатурой в базовых классах. А во втором случае функция с тем же именем заново не объявляется, а переопределяется уже объявленная функция базового класса.
Это позволяет динамически вызывать нужное определение одной и той же функции в зависимости от объекта, с которым функция вызывается.
Комментариев нет:
Отправить комментарий