Виртуальные методы без тела - PullRequest
22 голосов
/ 04 апреля 2011

Я искал код в абстрактном классе:

public virtual void CountX(){}

public virtual void DoCalculation() { ...code}

Зачем мне объявлять пустой виртуальный метод в абстрактном классе, если не обязательно переопределять его в производных типах?

Ответы [ 5 ]

43 голосов
/ 04 апреля 2011

Потому что, если поведение по умолчанию - ничего не делать, но производные классы могут захотеть что-то сделать.Это совершенно правильная структура.

Это позволяет вашему базовому коду вызывать ее.Вы склонны видеть похожие конструкции, когда есть код «BeforeXXX» и «AfterXXX», в базовом классе этот код пуст, но метод должен быть там для компиляции.В производных классах этот код является необязательным, но для его переопределения он должен быть виртуальным.

Тот факт, что он находится в абстрактном классе, не должен путать его поведение.

Пример:

  abstract class Base
    {
        public void ProcessMessages(IMessage[] messages)
        {
            PreProcess(messages);

            // Process.

            PostProcess(messages);
        }

        public virtual void PreProcess(IMessage[] messages)
        {
            // Base class does nothing.
        }

        public virtual void PostProcess(IMessage[] messages)
        {
            // Base class does nothing.
        }
    }

    class Derived : Base
    {
        public override void PostProcess(IMessage[] messages)
        {
            // Do something, log or whatever.
        }

        // Don't want to bother with pre-process.
    }

Если бы эти методы (Pre, Post) были абстрактными, то все производные классы нуждались бы для их реализации (вероятно, в виде пустых методов) - мусор кода, который можно удалить с помощью пустого виртуальногометоды на базе.

8 голосов
/ 04 апреля 2011

Как @Adam сказал вам, есть много случаев, в которых это имеет смысл.Когда вы создаете абстрактный класс, это потому, что вы хотите создать общий интерфейс для всех классов, производных от него;однако на этом уровне наследования у вас не будет достаточно информации для создания рабочего кода для этого метода.

Например, если вы создаете класс Figure , с *Метод 1005 * getArea () , вы не сможете написать код, который будет правильно рассчитывать площадь для всех фигур.Вам придется подождать, чтобы написать код для Rectangle или Circle (оба получены из Figure ), чтобы иметь возможность писать рабочий кодим.

5 голосов
/ 04 апреля 2011

Если это ОБЯЗАТЕЛЬНО для переопределения и никакие логики по умолчанию не могут быть записаны в базовом классе, то виртуальность неправильна, и метод должен быть абстрактным. Если действие по умолчанию - ничего не делать, то, как упомянул Адам, создание пустого виртуального метода в базовом классе - совершенно правильная структура

3 голосов
/ 04 апреля 2011

Когда вы объявляете метод как абстрактный, унаследованный класс имеет , чтобы переопределить этот метод (обеспечить реализацию).Это обязательно.

Когда метод объявлен как виртуальный, наследник может переопределить метод и предоставить реализацию, отличную от значения по умолчанию.

0 голосов
/ 08 сентября 2014

С точки зрения дизайна это плохо пахнет и указывает на то, что реализация проекта находится в незрелом состоянии.Если метод не требуется для каждого класса, который выводит конкретный базовый класс, то по определению он не принадлежит базовому классу.Обычно вы обнаружите, что этот метод используется определенными производными базового класса, и это указывает на новый интерфейс или уровень абстракции в вашей иерархии наследования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...