Полное руководство по языку программирования С# 14 и платформе .NET 10 / Интерфейсы

Применение интерфейсов

Начальный ⏱ 5 мин чтения 👁 2 🕓 обновлено 11.08.2026

Интерфейс представляет некое описание типа, набор компонентов, который должен иметь тип данных. И, собственно, мы не можем создавать объекты интерфейса напрямую с помощью конструктора, как например, в классах:


IMovable m = new IMovable(); // ! Ошибка, так сделать нельзя

interface IMovable
{
	void Move();
}

В конечном счете интерфейс предназначен для реализации в классах и структурах. Например, реализуем выше определенный интерфейс IMovable:


// применение интерфейса в классе
class Person : IMovable
{
	public void Move()
	{
		Console.WriteLine("Человек идет");
	}
}
// применение интерфейса в структуре
struct Car : IMovable
{
	public void Move()
	{
		Console.WriteLine("Машина едет");
	}
}

При применении интерфейса, как и при наследовании после имени класса или структуры указывается двоеточие и затем идут названия применяемых интерфейсов. При этом класс должен реализовать все методы и свойства применяемых интерфейсов, если эти методы и свойства не имеют реализации по умолчанию.

Если методы и свойства интерфейса не имеют модификатора доступа, то по умолчанию они являются публичными, при реализации этих методов и свойств в классе и структуре к ним можно применять только модификатор public.

Применение интерфейса в программе:


Person person = new Person();
Car car = new Car();
DoAction(person);
DoAction(car);

void DoAction(IMovable movable) => movable.Move();

interface IMovable
{
    void Move();
}
class Person : IMovable
{
    public void Move() => Console.WriteLine("Человек идет");
}
struct Car : IMovable
{
    public void Move() => Console.WriteLine("Машина едет");
}

В данной программе определен метод DoAction(), который в качестве параметра принимает объект интерфейса IMovable. На момент написания кода мы можем не знать, что это будет за объект - какой-то класс или структура. Единственное, в чем мы можем быть уверены, что этот объект обязательно реализует метод Move и мы можем вызвать этот метод.

Иными словами, интерфейс - это контракт, что какой-то определенный тип обязательно реализует некоторый функционал.

Консольный вывод данной программы:


Человек идет
Машина едет

Реализация интерфейсов по умолчанию

Начиная с версии C# 8.0 интерфейсы поддерживают реализацию методов и свойств по умолчанию. Зачем это нужно? Допустим, у нас есть куча классов, которые реализуют некоторый интерфейс. Если мы добавим в этот интерфейс новый метод, то мы будем обязаны реализовать этот метод во всех классах, применяющих данный интерфейс. Иначе подобные классы просто не будут компилироваться. Теперь вместо реализации метода во всех классах нам достаточно определить его реализацию по умолчанию в интерфейсе. Если класс не реализует метод, будет применяться реализация по умолчанию.


IMovable tom = new Person();
Car tesla = new Car();
tom.Move();     // Walking
tesla.Move();   // Driving
interface IMovable
{
    void Move() => Console.WriteLine("Walking");
}
class Person : IMovable { }
class Car : IMovable
{
    public void Move() => Console.WriteLine("Driving");
}

В данном случае интерфейс IMovable определяет реализацию по умолчанию для метода Move. Класс Person не реализует этот метод, поэтому он применяет реализацию по умолчанию в отличие от класса Car, который определяет свою реализацию для метода Move.

Стоит отметить, что хотя для объекта класса Person мы можем вызвать метод Move - ведь класс Person применяет интерфейс IMovable, тем не менее мы не можем написать так:


Person tom = new Person();
tom.Move();     // Ошибка - метод Move не определен в классе Person

Множественная реализация интерфейсов

Интерфейсы имеют еще одну важную функцию: в C# не поддерживается множественное наследование, то есть мы можем унаследовать класс только от одного класса, в отличие, скажем, от языка С++, где множественное наследование можно использовать. Интерфейсы позволяют частично обойти это ограничение, поскольку в C# классы и структуры могут реализовать сразу несколько интерфейсов. Все реализуемые интерфейсы указываются через запятую:


class myClass: myInterface1, myInterface2, myInterface3, ...
{
	
}

Рассмотрим на примере:


Message hello = new Message("Hello World");
hello.Print();	// Hello World

interface IMessage
{
    string Text { get; set; }
}
interface IPrintable
{
    void Print();
}
class Message : IMessage, IPrintable
{
    public string Text { get; set; }
    public Message(string text) => Text = text;
    public void Print()=> Console.WriteLine(Text);
}

В данном случае определены два интерфейса. Интерфейс IMessage определяет свойство Text, которое представляет текст сообщения. А интерфейс IPrintable определяет метод Print.

Класс Message реализует оба интерфейса и затем применяется в программе.

Интерфейсы в преобразованиях типов

Все сказанное в отношении преобразования типов характерно и для интерфейсов. Поскольку класс Message реализует интерфейс IMessage, то переменная типа IMessage может хранить ссылку на объект типа Message:


// Все объекты Message являются объектами IMessage
IMessage hello = new Message("Hello METANIT.COM");
Console.WriteLine(hello.Text); // Hello METANIT.COM

// Не все объекты IMessage являются объектами Message, необходимо явное приведение
// Message someMessage = hello; // ! Ошибка

// Интерфейс IMessage не имеет свойства Print, необходимо явное приведение
// hello.Print();  // ! Ошибка

// если hello представляет класс Message, выполняем преобразование
if (hello is Message someMessage) someMessage.Print();

Преобразование от класса к его интерфейсу, как и преобразование от производного типа к базовому, выполняется автоматически. Так как любой объект Message реализует интерфейс IMessage.

Обратное преобразование - от интерфейса к реализующему его классу будет аналогично преобразованию от базового класса к производному. Так как не каждый объект IMessage является объектом Message (ведь интерфейс IMessage могут реализовать и другие классы), то для подобного преобразования необходима операция приведения типов. И если мы хотим обратиться к методам класса Message, которые не определены в интерфейсе IMessage, но являются частью класса Message, то нам надо явным образом выполнить преобразование типов:

if (hello is Message someMessage) someMessage.Print();
Дополнительные материалы

Проверь себя

📋 Тест по теме «Применение интерфейсов» Тест по теме

Практические задания

Лёгкое Ручная проверка Заполните пропуск в коде (1)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

_____ m = new IMovable(); // ! Ошибка, так сделать нельзя

interface IMovable
{
	void Move();
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (2)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

// применение интерфейса в классе
class Person : _____
{
	public void Move()
	{
		Console.WriteLine("Человек идет");
	}
}
// применение интерфейса в структуре
struct Car : IMovable
{
	public void Move()
	{
		Console.WriteLine("Машина едет");
	}
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (3)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

Person person = _____ Person();
Car car = new Car();
DoAction(person);
DoAction(car);

void DoAction(IMovable movable) => movable.Move();

interface IMovable
{
    void Move();
}
class Person : IMovable
{
    public void Move() => Console.WriteLine("Человек идет");
}
struct Car : IMovable
{
    public void Move() => Console.WriteLine("Машина едет");
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (5)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

IMovable tom = new Person();
_____ tesla = new Car();
tom.Move();     // Walking
tesla.Move();   // Driving
interface IMovable
{
    void Move() => Console.WriteLine("Walking");
}
class Person : IMovable { }
class Car : IMovable
{
    public void Move() => Console.WriteLine("Driving");
}
Войдите, чтобы отправить решение
Среднее Ручная проверка Восстановите код по памяти (1)
+20 XP

В этом фрагменте кода урока пропущены два ключевых элемента. Впишите оба пропущенных значения через запятую в порядке появления (например: x, 5).

_____ m = new IMovable(); // ! Ошибка, так сделать нельзя

interface IMovable
{
	void _____();
}
Войдите, чтобы отправить решение
Среднее Ручная проверка Восстановите код по памяти (2)
+20 XP

В этом фрагменте кода урока пропущены два ключевых элемента. Впишите оба пропущенных значения через запятую в порядке появления (например: x, 5).

// применение интерфейса в классе
class _____ : IMovable
{
	public void Move()
	{
		Console._____("Человек идет");
	}
}
// применение интерфейса в структуре
struct Car : IMovable
{
	public void Move()
	{
		Console.WriteLine("Машина едет");
	}
}
Войдите, чтобы отправить решение
Среднее Ручная проверка Расставьте строки кода в правильном порядке
+20 XP

Строки кода из примера этого урока перемешаны. Впишите их в правильном порядке, каждую строку — с новой строки.

}
interface IMovable
{
	void Move();
IMovable m = new IMovable(); // ! Ошибка, так сделать нельзя
Войдите, чтобы отправить решение
Сложное Ручная проверка Объясните и модифицируйте пример из урока «Применение интерфейсов»
+30 XP

Опишите своими словами, что делает приведённый пример кода из урока «Применение интерфейсов», и предложите одно осмысленное изменение (например, другое входное значение или дополнительное условие). Приведите итоговый код.

IMovable m = new IMovable(); // ! Ошибка, так сделать нельзя

interface IMovable
{
	void Move();
}
Войдите, чтобы отправить решение
Сложное Ручная проверка Найдите потенциальную проблему в коде урока «Применение интерфейсов»
+30 XP

Изучите приведённый фрагмент кода и опишите, при каких входных данных или условиях он может сработать не так, как ожидается (граничный случай, отсутствие проверки и т.п.). Предложите исправленный вариант.

// применение интерфейса в классе
class Person : IMovable
{
	public void Move()
	{
		Console.WriteLine("Человек идет");
	}
}
// применение интерфейса в структуре
struct Car : IMovable
{
	public void Move()
	{
		Console.WriteLine("Машина едет");
	}
}
Войдите, чтобы отправить решение
Мини-проект Ручная проверка Мини-проект по теме «Применение интерфейсов»
+50 XP

Соберите небольшую программу, которая последовательно демонстрирует ключевые идеи урока. Программа должна быть рабочей и содержать минимум два самостоятельно написанных фрагмента, а не просто копию примера из урока.

Войдите, чтобы отправить решение
Домашнее задание Ручная проверка Домашнее задание по теме «Применение интерфейсов»
+25 XP

Напишите собственную небольшую программу, применяющую материал темы «Применение интерфейсов». Используйте не менее одной конструкции, показанной в примерах урока. Прикрепите код решения и краткое описание того, что он делает.

Войдите, чтобы отправить решение

Обсуждение (0)

Войдите, чтобы оставить комментарий.