Какая польза от "абстрактного переопределения" в C#?
Просто из любопытства я попытался переопределить абстрактный метод в базовом классе, а метод - абстрактную реализацию. Как показано ниже:
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 ответов
Для MSDN есть полезный пример - в основном вы можете заставить производный класс предоставить новую реализацию для метода.
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. Таким образом, абстрактный класс может заставить производные классы предоставлять новые реализации методов для виртуальных методов.,
Я считаю, что это действительно полезно для обеспечения надлежащего ToString()
реализация в производных классах. Допустим, у вас есть абстрактный базовый класс, и вы действительно хотите, чтобы все производные классы определяли значения ToString()
реализация, потому что вы активно используете его. Вы можете сделать это очень элегантно с abstract override
:
public abstract class Base
{
public abstract override string ToString();
}
Это явный сигнал для разработчиков, что ToString()
будет использоваться в базовом классе в некотором роде (например, запись вывода пользователю). Обычно они не думают об определении этого переопределения.
Интересно, что в версии Roslyn для компилятора C# есть абстрактный метод переопределения, который я нашел достаточно странным, чтобы написать статью о:
Представь это SecondAbstract
находится в середине иерархии трех классов, и он хочет реализовать некоторые абстрактные методы из своей базы FirstAbstract
оставляя некоторый другой метод X, который будет реализован от его потомка ThirdAbstract
,
В этом случае, SecondAbstract
вынужден украсить метод X abstract
поскольку он не хочет предоставлять реализацию; в то же время, он вынужден украшать его override
поскольку он не определяет новый метод X, но хочет перенести ответственность за реализацию X на его дочерний элемент. Следовательно, abstract override
,
В общем, концепции смоделированы abstract
а также override
ортогональны. Первая заставляет производные классы реализовывать метод, а вторая признает, что метод такой же, как указано в базовом классе, а не new
один.
Следовательно:
- ни одно из ключевых слов: "простой" метод
abstract
только: производный класс должен реализовыватьoverride
только: реализация метода, определенного в базовом классеabstract override
: производный класс должен реализовывать метод, определенный в базовом классе
Это сделано потому, что в детском классе вы не можете иметь abstract
метод с тем же именем, что и в базовом классе. override
сообщает компилятору, что вы переопределяете поведение базового класса.
Надеюсь, это то, что вы ищете.
Если вы не заявили SomeMethod
как abstract override
в SecondAbstract
компилятор будет ожидать, что этот класс будет содержать реализацию метода. С abstract override
ясно, что реализация должна быть в классе, производном от SecondAbstract
и не в SecondAbstract
сам.
Надеюсь это поможет...
Этот шаблон проектирования известен как шаблонный шаблон.
Страница Википедии о методах шаблонов
Простой, не программный пример: существует множество военных подразделений: танки, самолеты, солдаты, линейные корабли и т. Д. Все они должны реализовать некоторые общие методы, но будут реализовывать их совершенно по-разному:
- Переехать()
- Атака()
- Отступление ()
- Остальное()
так далее...