Какая польза от «абстрактного переопределения» в C #? - PullRequest
46 голосов
/ 18 января 2012

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

public abstract class FirstAbstract
{
    public abstract void SomeMethod();
}

public abstract class SecondAbstract : FirstAbstract
{
    public abstract override void SomeMethod();
    //?? what sense does this make? no implementaion would anyway force the derived classes to implement abstract method?
}

Любопытно узнать, почему компилятор C # позволяет писать «абстрактное переопределение».Разве это не избыточно?Должно быть ошибка времени компиляции, чтобы сделать что-то вроде этого.Служит ли он какому-либо варианту использования?

Спасибо за ваш интерес.

Ответы [ 7 ]

59 голосов
/ 18 января 2012

Есть полезный пример для этого на Документах Microsoft - в основном вы можете заставить производный класс предоставить новую реализацию для метода.

public class D
{
    public virtual void DoWork(int i)
    {
        // Original implementation.
    }
}

public abstract class E : D
{
    public abstract override void DoWork(int i);
}

public class F : E
{
    public override void DoWork(int i)
    {
        // New implementation.
    }
}

Если виртуальныйМетод объявлен абстрактным, он все еще виртуален для любого класса, наследуемого от абстрактного класса. Класс, унаследовавший абстрактный метод, не может получить доступ к исходной реализации метода - в предыдущем примере DoWork для класса F не может вызвать DoWork для класса D. Таким образом, абстрактный класс может принудительно вызвать производныйклассы для предоставления новых реализаций методов для виртуальных методов .

43 голосов
/ 21 июля 2013

Я считаю, что это действительно полезно для обеспечения правильной реализации ToString() в производных классах.Допустим, у вас есть абстрактный базовый класс, и вы действительно хотите, чтобы все производные классы определяли осмысленную реализацию ToString(), потому что вы активно используете ее.Вы можете сделать это очень элегантно с помощью abstract override:

public abstract class Base
{
    public abstract override string ToString();
}

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

12 голосов
/ 18 января 2012

Интересно, что в версии Roslyn для компилятора C # есть метод абстрактного переопределения, который я нашел достаточно странным, чтобы написать статью о:

http://ericlippert.com/2011/02/07/strange-but-legal/

6 голосов
/ 18 января 2012

Представьте себе, что SecondAbstract находится в середине иерархии трех классов, и он хочет реализовать некоторые абстрактные методы из своей базы FirstAbstract, оставляя при этом некоторый другой метод X для реализации из его дочернего элемента ThirdAbstract.

В этом случае SecondAbstract принудительно украшает метод X с помощью abstract, поскольку он не хочет предоставлять реализацию; в то же время, он вынужден украшать его override, поскольку он не определяет новый метод X, но хочет перенести ответственность за реализацию X на его дочерний элемент. Следовательно, abstract override.

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

Таким образом:

  • ни одно из ключевых слов: "простой" метод
  • abstract только: производный класс должен реализовывать
  • override только: реализация метода, определенного в базовом классе
  • abstract override: производный класс должен реализовывать метод, определенный в базовом классе
0 голосов
/ 09 июня 2014

Этот шаблон проектирования известен как шаблонный шаблон.

Страница Википедии о методах шаблонов

Простой пример, не связанный с программным обеспечением: существует множество военных подразделений: танки, самолеты, солдаты, линейные корабли и т. Д. Все они должны реализовать некоторые общие методы, но они будут реализовывать их совершенно по-разному:

  • Move ()
  • Атака ()
  • Retreat ()
  • Rest ()

и т.д ...

0 голосов
/ 18 января 2012

Если вы не объявите SomeMethod как abstract override в SecondAbstract, компилятор будет ожидать, что этот класс будет содержать реализацию метода.С abstract override ясно, что реализация должна быть в классе, производном от SecondAbstract, а не от SecondAbstract.

Надеюсь, это поможет ...

0 голосов
/ 18 января 2012

Это сделано потому, что в дочернем классе вы не можете иметь метод abstract с тем же именем, что и в базовом классе.override сообщает компилятору, что вы переопределяете поведение базового класса.

Надеюсь, это то, что вы ищете.

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