Страницы

Поиск по вопросам

среда, 10 октября 2018 г.

Отличия переопределения метода от перекрытия

Чем отличается перекрытие от переопределения метода?


Ответ

Перекрытие (в ваших терминах) означает, что метод в производном классе скрывает метод с той же самой сигнатурой в базовом классе.
Поэтому в 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` ^^^^^^^^^^^^^^^^^^^^^^^^
То есть в первом случае мы в каждом новом производном классе в иерархии классов объявляем новую функцию, которая скрывает функцию с той же сигнатурой в базовых классах. А во втором случае функция с тем же именем заново не объявляется, а переопределяется уже объявленная функция базового класса.
Это позволяет динамически вызывать нужное определение одной и той же функции в зависимости от объекта, с которым функция вызывается.

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

Отправить комментарий