Интерфейсы в C#: контракты для надежного ООП
Что такое интерфейс
Интерфейс — это синтаксический контракт, определяющий ЧТО должен делать класс, но не КАК. Содержит только объявления членов (методы, свойства, события, индексаторы) без реализации. Реализацию предоставляет класс, реализующий интерфейс.
Объявление интерфейса
public interface ITransaction
{
void ShowTransaction(); // метод
double Amount { get; set; } // свойство
event EventHandler Completed; // событие
string this[int index] { get; } // индексатор
}
По умолчанию все члены public (модификаторы доступа не указываются). Начиная с C# 8.0 можно иметь реализацию по умолчанию (default реализация), статические члены, private методы.
Реализация интерфейса
public class Transaction : ITransaction
{
public string Code { get; set; }
public string Date { get; set; }
private double _amount;
public double Amount
{
get => _amount;
set => _amount = value >= 0 ? value : throw new ArgumentException();
}
public void ShowTransaction()
{
Console.WriteLine($"Transaction: {Code}");
Console.WriteLine($"Date: {Date}");
Console.WriteLine($"Amount: {Amount}");
}
public event EventHandler Completed;
public string this[int index] => index == 0 ? Code : Date;
}
Явная реализация интерфейса
Если класс реализует несколько интерфейсов с одинаковыми сигнатурами, или нужно скрыть член от публичного API класса:
interface I1 { void Method(); }
interface I2 { void Method(); }
public class MyClass : I1, I2
{
void I1.Method() { Console.WriteLine("I1.Method"); }
void I2.Method() { Console.WriteLine("I2.Method"); }
public void Method() { Console.WriteLine("Public Method"); }
}
// Использование
MyClass obj = new MyClass();
obj.Method(); // Public Method
((I1)obj).Method(); // I1.Method
((I2)obj).Method(); // I2.Method
Интерфейсы vs Абстрактные классы
| Характеристика | Interface | Abstract Class |
|---|---|---|
| Множественная реализация | Класс может реализовывать много интерфейсов | Только один базовый класс |
| Поля | Только static const (до C# 8.0); теперь можно static поля | Любые поля |
| Конструкторы | Нет | Есть |
| Модификаторы доступа | public (по умолчанию), private/protected для default-реализаций (C# 8+) | Любые |
| Назначение | Контракт поведения (CAN-DO) | Общая реализация (IS-A) |
Интерфейсы по умолчанию (C# 8.0+)
public interface ILogger
{
void Log(string msg); // должен быть реализован
void LogWarning(string msg) // default реализация
{
Log($"WARN: {msg}");
}
static void StaticMethod() { } // статический член
private void Helper() { } // private метод (C# 8+)
}
Пример из оригинала
using System;
public interface ITransactions
{
void ShowTransaction();
double GetAmount();
}
public class Transaction : ITransactions
{
private string _code, _date;
private double _amount;
public Transaction(string c, string d, double a)
{
_code = c; _date = d; _amount = a;
}
public double GetAmount() => _amount;
public void ShowTransaction()
{
Console.WriteLine($"Transaction: {_code}");
Console.WriteLine($"Date: {_date}");
Console.WriteLine($"Amount: {_amount}");
}
}
class Program
{
static void Main()
{
var t1 = new Transaction("001", "8/10/2012", 78900);
var t2 = new Transaction("002", "9/10/2012", 451900);
t1.ShowTransaction();
t2.ShowTransaction();
}
}
Лучшие практики
- Именование: префикс
I(IComparable,IDisposable) - Интерфейсы должны быть маленькими и фокусированными (Interface Segregation Principle)
- Программируйте к интерфейсам, а не к реализациям (Dependency Inversion)
- Используйте
defaultреализации (C# 8+) для эволюции интерфейсов без ломания существующих реализаций - Рассмотрите
recordс интерфейсами для DTO
Язык C
- Работа с интерфейсом командной строки в SPICE
- Освоение интерфейсов в C#: определение, реализация и практические примеры
- Интерфейсы в Java: концепции, реализация и лучшие практики
- Интерфейс Collection в Java: основные концепции и ключевые методы
- Освоение интерфейса NavigableSet в Java: навигация, сортировка и практические примеры
- Освоение Java Lambda-выражений: от основ к Stream API
- Надежный беспроводной датчик подъездной дороги для длинных подъездов — простое подключение к Raspberry Pi
- Интерфейсы в Java: определение, использование и лучшие практики
- Интерфейсы в C++: абстрактные классы и чисто виртуальные функции
- Java 9 Private Interface Methods: инкапсуляция и повторное использование кода