В чем разница между абстрактным класом и интерфейсом
Абстрактный класс — это базовый тип, который может содержать реализацию методов и состояние, а интерфейс — это контракт, определяющий только сигнатуры членов, которые должны быть реализованы в классе. В C# класс может наследовать только один абстрактный класс, но может реализовывать множество интерфейсов.
Как это работает
Абстрактный класс объявляется с ключевым словом abstract. Он может содержать как абстрактные методы (без реализации), так и обычные методы с реализацией, поля, свойства, конструкторы. Это позволяет задать общую логику для группы родственных классов. Например, абстрактный класс Aircraft может содержать поле MaxSpeed, реализацию метода StartEngine() и абстрактный метод Fly().
Интерфейс в C# объявляется с ключевым словом interface. До C# 8.0 интерфейсы могли содержать только сигнатуры методов, свойств, событий и индексаторов без реализации. Начиная с C# 8.0 появились методы с реализацией по умолчанию, но основное назначение интерфейса — определить контракт, который обязуется выполнить класс. Интерфейс не может содержать полей и конструкторов.
Пример
// Абстрактный класс
public abstract class Aircraft
{
public int MaxSpeed { get; set; }
public void StartEngine()
{
Console.WriteLine("Engine started");
}
// Абстрактный метод — должен быть реализован в наследнике
public abstract void Fly();
}
// Интерфейс
public interface IFlyable
{
void Fly();
}
// Класс может наследовать один абстрактный класс и несколько интерфейсов
public class Boeing : Aircraft, IFlyable
{
public override void Fly()
{
Console.WriteLine("Boeing is flying");
}
}Подводные камни
- Множественное наследование: C# не поддерживает множественное наследование классов, поэтому класс может иметь только один базовый абстрактный класс. Интерфейсов можно реализовать сколько угодно. Это ключевое различие, которое часто определяет выбор.
- Состояние: Абстрактный класс может хранить состояние (поля), интерфейс — нет. Если нужно передать общие данные, выбирайте абстрактный класс.
- Реализация по умолчанию: В C# 8+ интерфейсы могут иметь реализацию по умолчанию, но это не делает их заменой абстрактных классов — они всё ещё не могут иметь полей.
- Семантика: Абстрактный класс описывает «что это» (is-a), интерфейс — «что умеет» (can-do). Например,
Aircraft— это тип, аIFlyable— способность.
Когда использовать
Выбирайте абстрактный класс, когда:
- Есть общая реализация, которую нужно переиспользовать в нескольких классах.
- Нужны поля, конструкторы или модификаторы доступа (protected, private).
- Классы логически связаны и образуют иерархию.
Выбирайте интерфейс, когда:
- Нужно определить контракт для несвязанных классов (например,
IComparableдля сравнения). - Нужна поддержка множественного наследования поведения.
- Нужно отделить определение API от реализации (например, для тестирования с моками).
Коротко
- Абстрактный класс — это частично реализованный базовый класс; интерфейс — чистый контракт.
- Класс наследует один абстрактный класс, но реализует много интерфейсов.
- Абстрактный класс может содержать поля и реализацию; интерфейс — только сигнатуры (до C# 8) или методы с реализацией по умолчанию.
- Выбор зависит от того, нужна ли общая логика (абстрактный класс) или только обязательства (интерфейс).
