Подтвердить что ты не робот

Виртуальные методы без тела

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

public virtual void CountX(){}

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

Он позволяет вашему базовому коду называть его. Вы, как правило, видите подобные проекты, когда есть код "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) были абстрактными, тогда все производные классы должны были реализовать их (вероятно, как пустые методы) - подстилку кода, которую можно удалить с помощью пустых виртуальных методов в базе.

Ответ 3

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

Ответ 4

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

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

Ответ 5

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