Neitralov Neitralov

Привет, я Максим Осин

Backend • Frontend • DevOps

Россия, г. Казань

Разница между абстрактным классом и интерфейсом в 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, который определяет, что каждый объект, который его реализует, может столкнуться с главным героем и будет обладать при этом своей собственной логикой при столкновении:

  • Монетки увеличивают счетчик очков и приближают к победе.
  • Аптечки увеличивают запас здоровья главного героя.
  • Враги таранят главного героя и уменьшают значение его счетчика здоровья.

Заключение

Итоговый ответ на вопрос можно сформулировать следующим образом:

«Технически границы между абстрактным классом и интерфейсом слегка размыты из-за возможности реализовывать логику в интерфейсе, но архитектурно они остаются разными: абстрактный класс — это основа для цепочки наследования с общим состоянием, а интерфейс — это контракт для множественного использования. Абстрактный класс стоит выбрать, когда наследники логически являются вариациями одного базового типа, а интерфейс — когда необходимо определить поведение, которое может быть у несвязанных объектов.»