При реализации принципа наследования базовый класс воплощает НАИБОЛЕЕ ОБЩИЕ черты разрабатываемого семейства классов. Поэтому на этапе разработки базового класса часто бывает достаточно лишь обозначить множество функций, которые будут определять основные черты поведения объектов-представителей производных классов.
Если базовый класс объявляется исходя из следующих предпосылок:
§ базовый класс используется исключительно как основа для объявления классов-наследников,
§ базовый класс никогда не будет использован для определения объектов,
§ часть функций-членов (возможно, все) базового класса в обязательном порядке переопределяется в производных классах,
то определение таких функций даже в самых общих чертах (заголовок функции и тело, содержащее вариант оператора return) в базовом классе лишено всякого смысла.
class X
{
public int f0()
{
// Если в соответствии с замыслом разработчика, этот код ВСЕГДА будет недоступен,
// то зачем он в принципе нужен?
return 0;
}
}
class Y:X
{
new public void f0()
{
::::::::::
// Здесь размещается код переопределённой функции.
::::::::::
return 0;
}
}
Такой код никому не нужен и C# позволяет избегать таких странных конструкций. Вместо переопределяемой “заглушки” можно использовать объявление абстрактной функции.
Синтаксис объявления абстрактной функции предполагает использование ключевого слова abstract и полное отсутствие тела. Объявление абстрактной функции завершается точкой с запятой.
Класс, содержащий вхождения абстрактных (хотя бы одной!) функций также должен содержать в заголовке объявления спецификатор abstract.
В производном классе соответствующая переопределяемая абстрактная функция обязательно должна включать в заголовок функции спецификатор override. Его назначение – явное указание факта переопределения абстрактной функции.
Абстрактный класс фактически содержит объявления нереализованных функций базового класса. На основе абстрактного класса невозможно определить объекты. Попытка создания соответствующего объекта-представителя абстрактного класса приводит к ошибке, поскольку в классе не определены алгоритмы, определяющие поведение объект.
abstract class X // Абстрактный класс с одной абстрактной функцией.
{
public abstract int f0();
}
class Y:X
{
// Переопределение абстрактной функции должно
// содержать спецификатор override.
public override void f0()
{
::::::::::
return 0;
}
}
::::::::::
static void Main(string[] args)
{
X x = new X(); // NO!
Y y0 = new Y(125);
// Работает переопределённая абстрактная функция!
y0.f0();
}
Ещё пример
using System;
namespace Interface01
{
// Абстрактный класс.
abstract class aX1
{
public int xVal;
// Его конструкторы могут использоваться при построении