Страницы

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

среда, 27 ноября 2019 г.

Зачем нужно ключевое слово override

#c_sharp #ооп


Есть 2 класса. Class2 содержит публичный виртуальный метод:

    public virtual void fun()
    {
        Console.WriteLine("1");
    }


Class1 наследуется от Class2 и переписывает fun 

class Class1 : Class2
{
    public override void fun()
    {
        base.fun();
        Console.WriteLine("2");
    }  
}


Если создать объект Class1 и вызвать fun

Class1 cl = new Class1();
cl.fun();


на консоль будет выведено 1 и 2. Однако если удалить override и оставить :

class Class1 : Class2
{
    public   void fun()
    {
        base.fun();
        Console.WriteLine("2");
    }  
}


то на консоль опять же выведет 1 и 2. Вопрос: зачем нужно ключевое слово override
которое никак не влияет на результат? Понятно, что по идеи мы переписываем виртуальные
методы внутри тел методов наследников, но для этого достаточно в базовом классе написать
virtual, а в наследнике создать одноименный метод и вызвать base. Так получается, что
слово  override не нужно?
    


Ответы

Ответ 1



Ключевое слово override нужно не компилятору (он-то прекрасно может увидеть, что метод базового класса виртуальный), а нам с вами, чтобы предотвратить ошибки. Смотрите, пусть у нас была пара из виртуального метода и его переопределения, и мы переименовали виртуальный метод, а переименовать переопределение забыли. Или мы поменяли сигнатуру базового метода, а при смене сигнатуры переопределённого метода допустили ошибку в порядке аргументов. Или просто имплементируем виртуальный метод, но сделали ошибку в сигнатуре. Если бы ключевое слово override не требовалось, компилятор прекрасно проглотил бы этот код: ну базовый метод виртуальный, а новый метод его не переопределяет, а просто определяет параллельный метод. А вот с ключевым словом override компилятор может поднять тревогу: override не перекрывает никакой метод, это явная ошибка. Кроме того, ключевое override помогает читателю понять, что это метод в цепочке перекрытий базового метода, и он будет вызван полиморфно. Без него пришлось бы лезть во все базовые классы и подглядывать там, нет ли там случайно виртуального метода с точно такой же сигнатурой. Как отмечает @Алексей Шиманский в комментариях, если опустить ключевое слово override в вашем примере, то функция Class1.fun будут перекрывать по имени, но не виртуально переопределять функцию базового класса Class2.fun (и компилятор пожалуется, что вы не указали ключевое слово new, которое означает, что вы так делаете сознательно, а не по ошибке). Для вызова по точному типу объекта разницы нет, но разница будет, если вызывать по ссылке на базовый тип: Class2 cl = new Class1(); cl.fun(); В этом случае Class2.fun и Class1.fun — несвязанные функции, и несмотря на virtual у Class2.fun, будет вызвана лишь функция базового класса. Смысл виртуальных функций в том и состоит, что по ссылке на базовый класс будет вызвана реализация виртуальной функции из производного класса. (Вы можете не знать точный тип объекта во время выполнения.)

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

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