abstract (Справочник по C#)
Модификатор abstract
указывает, что изменяемый элемент имеет отсутствующую или неполную реализацию. Модификатор abstract можно использовать с классами, методами, свойствами, индексаторами и событиями. Используйте модификатор abstract
в объявлении класса, чтобы указать, что класс предназначен только для использования в качестве базового класса для других классов и не должен быть создан сам по себе. Элементы с пометкой abstract должны быть реализованы не абстрактными классами, производными от абстрактного класса.
Пример 1
В этом примере класс Square
должен обеспечивать реализацию GetArea
, поскольку является производным от класса Shape
:
abstract class Shape
{
public abstract int GetArea();
}
class Square : Shape
{
private int _side;
public Square(int n) => _side = n;
// GetArea method is required to avoid a compile-time error.
public override int GetArea() => _side * _side;
static void Main()
{
var sq = new Square(12);
Console.WriteLine($"Area of the square = {sq.GetArea()}");
}
}
// Output: Area of the square = 144
Абстрактные классы предоставляют следующие возможности:
Создавать экземпляры абстрактного класса нельзя.
Абстрактный класс может содержать абстрактные методы и методы доступа.
Изменить абстрактный класс с модификатором sealed нельзя, так как два этих модификатора имеют взаимоисключающие значения. Модификатор
sealed
запрещает наследование класса, в то время как модификаторabstract
указывает, что класс обязан иметь производные классы.Неабстрактный класс, производный от абстрактного класса, должен включать фактические реализации всех наследуемых абстрактных методов и методов доступа.
Модификатор abstract
в объявлении метода или свойства позволяет указать, что этот метод или свойство не содержат реализации.
Абстрактные методы предоставляют следующие возможности:
Абстрактный метод неявно представляет собой виртуальный метод.
Объявления абстрактных методов допускаются только в абстрактных классах.
Поскольку объявление абстрактного метода не предоставляет фактической реализации, тело метода отсутствует, а объявление метода заканчивается точкой с запятой, и фигурных скобок ({ }) после подписи нет. Например:
public abstract void MyMethod();
Реализация предоставляется методом override, который является членом неабстрактного класса.
В объявлении абстрактного метода нельзя использовать статические или виртуальные модификаторы.
Действие абстрактных свойств аналогично абстрактным методам, за исключением отличий в синтаксисе объявлений и вызовов.
Использование модификатора
abstract
в статическом свойстве является недопустимым.Абстрактное наследуемое свойство можно переопределить в производном классе, включив объявление свойства, которое использует модификатор override.
Дополнительные сведения об абстрактных классах см. в статье Abstract and Sealed Classes and Class Members (Абстрактные и запечатанные классы и члены классов).
Абстрактный класс должен предоставлять реализацию для всех членов интерфейса.
Абстрактный класс, реализующий интерфейс, может сопоставлять методы интерфейса с абстрактными методами. Например:
interface I
{
void M();
}
abstract class C : I
{
public abstract void M();
}
Пример 2
В следующем примере класс DerivedClass
является производным от абстрактного класса BaseClass
. Абстрактный класс содержит абстрактный метод, AbstractMethod
, и два абстрактных свойства, X
и Y
.
// Abstract class
abstract class BaseClass
{
protected int _x = 100;
protected int _y = 150;
// Abstract method
public abstract void AbstractMethod();
// Abstract properties
public abstract int X { get; }
public abstract int Y { get; }
}
class DerivedClass : BaseClass
{
public override void AbstractMethod()
{
_x++;
_y++;
}
public override int X // overriding property
{
get
{
return _x + 10;
}
}
public override int Y // overriding property
{
get
{
return _y + 10;
}
}
static void Main()
{
var o = new DerivedClass();
o.AbstractMethod();
Console.WriteLine($"x = {o.X}, y = {o.Y}");
}
}
// Output: x = 111, y = 161
В предыдущем примере при попытке создать экземпляр абстрактного класса с помощью оператора вида:
BaseClass bc = new BaseClass(); // Error
Выдается сообщение об ошибке, указывающее, что компилятор не может создать экземпляр абстрактного класса BaseClass.
Тем не менее можно использовать конструктор абстрактного класса, как показано в примере ниже.
Пример 3
public abstract class Shape
{
public string Color { get; set; }
// Constructor of the abstract class
protected Shape(string color)
{
Color = color;
Console.WriteLine("Created a shape with color {color}.");
}
// Abstract method that must be implemented by derived classes
public abstract double CalculateArea();
}
public class Square : Shape
{
public double Side { get; set; }
// Constructor of the derived class calling the base class constructor
public Square(string color, double side) : base(color)
{
Side = side;
}
public override double CalculateArea()
{
return Side * Side;
}
}
public class Program
{
public static void Main(string[] args)
{
Square square = new Square("red", 5);
Console.WriteLine("Area of the square: {square.CalculateArea()}");
}
}
Класс Shape
объявляется abstract
, что означает, что он не может быть создан напрямую. Вместо этого он служит схемой для других классов.
- Несмотря на то, что объекты абстрактного класса невозможно создать, он по-прежнему может иметь конструктор. Этот конструктор обычно
protected
, то есть доступ к нему можно получить только из производных классов. В этом случае конструкторShape
принимает параметрcolor
и инициализирует свойствоColor
. Он также выводит сообщение в консоль. Частьpublic Square(string color, double side) : base(color)
вызывает конструктор базового класса (Shape
) и передает в него аргументcolor
. - В классе Shape определенный конструктор принимает цвет в качестве параметра
protected Shape(string color)
. Это означает, что C# больше не предоставляет конструктор без параметров по умолчанию, поэтому производные классы должны использовать выражение: base(color)
для вызова базового конструктора. Установка значения по умолчанию для цветаprotected Shape(string color="green")
позволит опустить выражение: base(color)
в производных классах, при этом будет вызван конструкторprotected Shape(string color="green")
, устанавливающий цвет зелёный.
Спецификация языка C#
Дополнительные сведения см. в спецификации языка C#. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.