Почему я могу абстрагироваться от абстрактного метода?

У меня есть абстрактный базовый класс:

abstract class Foo
{
    virtual void DoSomeStuff()
    {
        //Do Some Stuff
    }

    abstract void DoSomeCrazyStuff();
}

И еще один абстрактный класс, полученный из этого:

abstract class Bar : Foo
{
    abstract override void DoSomeStuff();

    abstract override void DoSomeCrazyStuff();
}

Я понимаю, почему вы хотите абстрагироваться от переопределения DoSomeStuff() - для этого потребуется новая реализация для дополнительных производных классов. Но я не могу понять, почему вы хотите абстрагироваться от переопределения DoSomeCrazyStuff(). Насколько я могу судить, он избыточен - я уверен, что его удаление будет иметь отрицательный эффект.

Есть ли какой-то прецедент, когда абстрактное переопределение на абстрактном языке делает что-то полезное? Если нет, то почему нет сообщения о компиляторе, сообщающем мне, что то, что я написал, ничего не делает?

Ответ 1

  Почему я могу абстрактно переопределить абстрактный метод?

Для начала, нет никаких практических причин для предотвращения этого. Если это приведет к ошибке компилятора, все, что нужно сделать, это сделать класс более хрупким. Например:

abstract class Foo
{
    virtual void DoSomeStuff()
    {
        //Do Some Stuff
    }
}

abstract class Bar : Foo
{
    abstract override void DoSomeStuff();
}

Если абстрактное переопределение абстрактного было недопустимым, изменение DoSomeStuff для Foo на абстрактное теперь предотвратит компиляцию Bar. Абстрактное переопределение является избыточным, но не имеет потенциальных отрицательных побочных эффектов, поэтому компилятор в порядке с этим.


Почему нет предупреждения компилятора о том, что то, что я написал, ничего не делает?

Компилятор выдает предупреждения для определенных вещей, представляющих риск: неявное скрытие метода, недоступный код, использование устаревших методов и т.д. Единственная "проблема", которую может указывать ненужное абстрактное переопределение, заключается в том, что код был написан неэффективно. Это не то, о чем заботится компилятор.


Is there some use case where abstract override on an abstract does something useful?

Есть ли какой-то вариант использования, когда абстрактное переопределение абстрактного делает что-то полезное? Не функционально. Однако есть несколько случаев, когда вы можете сделать это намеренно:

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

Ответ 2

Явным образом abstract override вводя его в Bar, вы убедитесь, что он будет рассматриваться как абстрактный от Bar потомков, хотя в будущем в Foo он может быть изменен на не абстрактный. Несмотря на такое изменение, потомки Bar будут работать с одним и тем же контрактом.