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

Каково использование "абстрактного переопределения" в С#?

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

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?
}

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

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

4b9b3361

Ответ 1

Это полезный пример для Microsoft Docs - в основном вы можете заставить производный класс предоставить новую реализацию для метода.

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. Таким образом, абстрактный класс может заставить производные классы предоставлять новые реализации методов для виртуальных методов.,

Ответ 2

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

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

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

Ответ 3

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

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

Ответ 4

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

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

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

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

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

Ответ 5

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

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

Ответ 6

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

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

Ответ 7

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

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

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

  • Переместить()
  • Атака()
  • Отступление()
  • Остальной()

и т.д...