Ответ
Абстрактный класс в C# — это класс, который служит исключительно в качестве базового для других классов. Его нельзя инстанцировать напрямую с помощью оператора new. Основная цель — определить общий контракт (частичную реализацию) для группы родственных классов.
Ключевые характеристики:
- Нельзя создать экземпляр:
var obj = new AbstractClass();// Ошибка компиляции. - Может содержать абстрактные члены: Методы, свойства, индексаторы или события без реализации. Они помечаются словом
abstractи обязывают производные неабстрактные классы предоставить свою реализацию с помощьюoverride. - Может содержать обычные члены с реализацией: Поля, свойства, методы, конструкторы. Это позволяет вынести общую логику в базовый класс и избежать дублирования кода.
- Может иметь модификатор доступа: Например,
protected abstractметод.
Пример, демонстрирующий общую логику и контракт:
using System;
abstract class Document
{
// Обычное свойство с реализацией (общая логика)
public string Title { get; set; }
public string Author { get; set; }
public DateTime Created { get; } = DateTime.Now;
// Абстрактный метод (контракт, который нужно реализовать)
public abstract void Print();
// Обычный виртуальный метод (общая логика, которую можно переопределить)
public virtual void Save()
{
Console.WriteLine($"Документ '{Title}' сохранён в базовом хранилище.");
}
// Конструктор в абстрактном классе допустим
protected Document(string title, string author)
{
Title = title;
Author = author;
}
}
class PdfDocument : Document
{
public int PageCount { get; set; }
public PdfDocument(string title, string author) : base(title, author) { }
// Реализация абстрактного метода ОБЯЗАТЕЛЬНА
public override void Print()
{
Console.WriteLine($"Печать PDF '{Title}' ({PageCount} стр.).");
}
// Переопределение виртуального метода (опционально)
public override void Save()
{
base.Save(); // Можно вызвать базовую реализацию
Console.WriteLine("Дополнительно: зашифровано и добавлена цифровая подпись.");
}
}
class WordDocument : Document
{
public WordDocument(string title, string author) : base(title, author) { }
public override void Print()
{
Console.WriteLine($"Печать Word-документа '{Title}'.");
}
// Метод Save не переопределён, будет использована реализация из базового класса.
}
// Использование:
Document doc1 = new PdfDocument("Отчёт", "Иван") { PageCount = 10 };
Document doc2 = new WordDocument("Письмо", "Анна");
doc1.Print(); // Печать PDF 'Отчёт' (10 стр.).
doc1.Save(); // Вызовет переопределённый Save из PdfDocument.
doc2.Print(); // Печать Word-документа 'Письмо'.
// doc2.Save(); // Вызовет базовый метод Save из Document.
Когда использовать абстрактный класс, а не интерфейс?
- Абстрактный класс: Когда у производных классов есть чёткая иерархическая связь "is-a" (PdfDocument является Document) и нужно предоставить общую реализацию для части функциональности или состояние (поля).
- Интерфейс: Когда нужно определить контракт, который могут реализовать несвязанные классы. C# 8.0+ позволяет добавлять реализацию по умолчанию и в интерфейсы, но они по-прежнему не могут содержать поля экземпляра.