Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Модификатор abstract указывает, что целевой объект имеет недостающую или неполную реализацию. Используйте абстрактный модификатор с классами, методами, свойствами, индексаторами и событиями. Используйте модификатор abstract в объявлении класса, чтобы указать, что класс предназначен только для использования в качестве базового класса для других классов и не должен быть создан сам по себе. Не абстрактные классы, производные от абстрактного класса, должны реализовывать элементы, помеченные как абстрактные.
Справочные документы по языку C# описывают последнюю выпущенную версию языка C#. Она также содержит начальную документацию по функциям в общедоступных предварительных версиях для предстоящего языкового выпуска.
Документация определяет любую функцию, впервые представленную в последних трех версиях языка или в текущих общедоступных предварительных версиях.
Подсказка
Чтобы узнать, когда функция впервые появилась в C#, ознакомьтесь со статьей об истории версий языка C#.
Абстрактные классы могут содержать абстрактные члены (которые не имеют реализации и должны быть переопределены в производных классах) и полностью реализованные члены (например, обычные методы, свойства и конструкторы). Эта функция позволяет абстрактным классам предоставлять общие функциональные возможности, не требуя реализации конкретных абстрактных элементов производных классов.
Замечание
Элементы интерфейса по abstract умолчанию.
Абстрактный класс с смешанными элементами
В следующем примере демонстрируется абстрактный класс, содержащий как реализованные методы, так и абстрактные члены:
namespace LanguageKeywords;
public abstract class Vehicle
{
protected string _brand;
// Constructor - implemented method in abstract class
public Vehicle(string brand) => _brand = brand;
// Implemented method - provides functionality that all vehicles share
public string GetInfo() => $"This is a {_brand} vehicle.";
// Another implemented method
public virtual void StartEngine() => Console.WriteLine($"{_brand} engine is starting...");
// Abstract method - must be implemented by derived classes
public abstract void Move();
// Abstract property - must be implemented by derived classes
public abstract int MaxSpeed { get; }
}
public class Car : Vehicle
{
public Car(string brand) : base(brand) { }
// Implementation of abstract method
public override void Move() => Console.WriteLine($"{_brand} car is driving on the road.");
// Implementation of abstract property
public override int MaxSpeed => 200;
}
public class Boat : Vehicle
{
public Boat(string brand) : base(brand) { }
// Implementation of abstract method
public override void Move() => Console.WriteLine($"{_brand} boat is sailing on the water.");
// Implementation of abstract property
public override int MaxSpeed => 50;
}
public class AbstractExample
{
public static void Examples()
{
// Cannot instantiate abstract class: Vehicle v = new Vehicle("Generic"); // Error!
Car car = new Car("Toyota");
Boat boat = new Boat("Yamaha");
// Using implemented methods from abstract class
Console.WriteLine(car.GetInfo());
car.StartEngine();
// Using abstract methods implemented in derived class
car.Move();
Console.WriteLine($"Max speed: {car.MaxSpeed} km/h");
Console.WriteLine();
Console.WriteLine(boat.GetInfo());
boat.StartEngine();
boat.Move();
Console.WriteLine($"Max speed: {boat.MaxSpeed} km/h");
}
}
class Program
{
static void Main()
{
AbstractExample.Examples();
}
}
/* Output:
This is a Toyota vehicle.
Toyota engine is starting...
Toyota car is driving on the road.
Max speed: 200 km/h
This is a Yamaha vehicle.
Yamaha engine is starting...
Yamaha boat is sailing on the water.
Max speed: 50 km/h
*/
В этом примере абстрактный Vehicle класс предоставляет:
-
Реализованные элементы:
GetInfo()метод,StartEngine()метод и конструктор — эти члены предоставляют общие функциональные возможности для всех транспортных средств. -
Абстрактные члены:
Move()метод иMaxSpeedсвойство — эти элементы должны быть реализованы по каждому конкретному типу транспортного средства.
Эта конструкция позволяет абстрактным классам предоставлять общие функциональные возможности, гарантируя, что производные классы реализуют поведение, зависящее от транспортного средства.
Конкретный класс, производный от абстрактного класса
В этом примере класс 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, который является членом не абстрактного класса.Это ошибка использования
staticмодификаторов илиvirtualмодификаторов в объявлении абстрактного метода в типеclass. Вы можете объявлятьstatic abstractиstatic virtualметоды в интерфейсах.Действие абстрактных свойств аналогично абстрактным методам, за исключением отличий в синтаксисе объявлений и вызовов.
Это ошибка использования
abstractмодификатора для статического свойства в типеclass. Можно объявить илиstatic virtualсвойства в объявленияхstatic abstractинтерфейса.Абстрактное унаследованное свойство можно переопределить в производном классе, включив объявление свойства, использующее
overrideмодификатор.
Дополнительные сведения об абстрактных классах см. в статье Abstract and Sealed Classes and Class Members (Абстрактные и запечатанные классы и члены классов).
Абстрактный класс должен предоставлять реализацию для всех членов интерфейса. Абстрактный класс, реализующий интерфейс, может сопоставлять методы интерфейса с абстрактными методами. Например:
interface I
{
void M();
}
abstract class C : I
{
public abstract void M();
}
В следующем примере класс 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. Тем не менее можно использовать конструктор абстрактного класса, как показано в следующем примере.
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#.