Страницы

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

понедельник, 2 декабря 2019 г.

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

#c_sharp #классы #функции #виртуальная_функция


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


Ответы

Ответ 1



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

Ответ 2



Переопределение виртуального метода базового класса — это создание метода в порождённом классе, имеющим точно такую же сигнатуру (и отмеченным специальным ключевым словом). При этом для связки виртуальный метод + его переопределение действует позднее связывание: вызов метода по ссылке на базовый класс может привести к вызову перегруженного метода. Переопределений невиртуальных методов не бывает. Перекрытие метода — это просто определение в классе или производном от него метода с таким же именем (и возможно отличающейся сигнатурой). При этом который из двух методов будет вызван, известно во время компиляции.

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

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