Разница между абстрактным классом и интерфейсом в C#
15 августа 2026 г.
Эти два типа являются настолько схожими (особенно для новичков), что вопрос «Какая разница между абстрактным классом и интерфейсом?» является одним из самых популярных на собеседованиях для C# разработчиков.
В этом материале разберемся в этой разнице и выведем тот самый ответ, который обычно ожидают услышать.
Абстрактный класс
Абстрактный класс — класс, объявленный с ключевым словом abstract, экземпляр которого нельзя создать.
Пример:
// Определение абстрактного класса
public abstract class A
{
// Поле класса
private string _someField;
// Свойство класса
private int SomeProperty { get; set; }
// Конструктор
protected A()
{
// Тело конструктора
}
// Метод с базовой логикой, который можно переопределить
protected virtual void FirstMethod()
{
// Базовая логика...
}
// Абстрактный метод без базовой логики. Будет реализован в наследниках
public abstract void SecondMethod();
}
// Создаем новый класс B, который наследует абстрактный класс A
public class B : A
{
// Конструктор c вызовом конструктора родителя
public B() : base()
{
// Тело конструктора
}
// FirstMethod может быть без переопределния. Тогда используем базовую логику
// Абстрактный метод, который мы обязаны реализовать
public override void SecondMethod();
}
Назначение такого класса: предоставлять общую логику для своих дочерних классов, которые будут от него наследованы.
Ключевые характеристики:
- Может иметь конструктор, который будет вызываться через
base()в дочерних классах. - Может содержать поля.
- Может содержать методы с реализацией.
- В C# класс может наследовать только один абстрактный класс.
Интерфейс
Интерфейс — контракт, который определяет какие методы, свойства, события и индексаторы должны быть реализованы в классе или структуре.
Пример:
// Определение интерфеса
interface IMoveable
{
// Свойство интерфейса (автосвойства с set; добавлять нельзя)
int Speed { get; }
// Метод интерфейса
void Move();
}
// Реализация интерфейса IMoveable классом Person
public class Person : IMoveable
{
public int Speed => 5;
public void Move()
{
// Логика передвижения
}
}
Ключевые характеристики:
- Определяет поведение класса или структуры.
- Не может определять состояние. Никаких полей и автосвойств (они создают скрытое поле «под капотом»).
- В C# класс/структура может реализовывать (наследовать) множество интерфейсов.
Интересный момент №1: поскольку структура (struct) не может быть унаследована от другой структуры или класса,
то наследование интерфейса это единственный вариант добавить общую логику между структурами.
Интересный момент №2: начиная с C# 8.0 появилась возможность добавить реализацию методам интерфейса. Это слегка стерло грань между абстрактным классом и интерфейсом.
Когда и что использовать?
Выбор абстрактного класса или интерфейса на текущий момент скорее вопрос семантики. Все зависит от архитектурного смысла, который необходимо вложить в код.
Выбираем абстрактный класс
Абстрактный класс выбирается, когда необходимо подчеркнуть наличие иерархии с общей сущностью. Дочерние сущности как бы являются родительской сущностью.
На примере компьютерной игры у нас может быть множество врагов. Каждый отдельный враг может являться наследником абстрактного класса Enemy, который описывает, что:
- Каждый враг имеет счетчик здоровья, который определяет его жизненное состояние.
- Каждый враг может перемещаться и имеет базовую логику передвижения, которая может быть переопределена и отличаться у врагов особого класса.
Выбираем интерфейс
Интерфейс выбирается, когда мы описываем поведение, которое может быть применено к разным типам объектов, которые не обязательно должны быть связаны какой-либо иерархией.
На примере все той же компьютерной игры. У нас может быть множество объектов, с которыми может столкнуться главный герой.
Каждый такой объект может реализовывать интерфейс ICollidableWithPlayer, который определяет, что каждый объект, который его реализует,
может столкнуться с главным героем и будет обладать при этом своей собственной логикой при столкновении:
- Монетки увеличивают счетчик очков и приближают к победе.
- Аптечки увеличивают запас здоровья главного героя.
- Враги таранят главного героя и уменьшают значение его счетчика здоровья.
Заключение
Итоговый ответ на вопрос можно сформулировать следующим образом:
«Технически границы между абстрактным классом и интерфейсом слегка размыты из-за возможности реализовывать логику в интерфейсе, но архитектурно они остаются разными: абстрактный класс — это основа для цепочки наследования с общим состоянием, а интерфейс — это контракт для множественного использования. Абстрактный класс стоит выбрать, когда наследники логически являются вариациями одного базового типа, а интерфейс — когда необходимо определить поведение, которое может быть у несвязанных объектов.»