← Назад к вопросам

В чем разница между интерфейсом и классом в C#?

1.3 Junior🔥 101 комментариев
#Другое

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между интерфейсом и классом в C#

Хотя я как Data Scientist в основном работаю с Python, понимание различий между интерфейсом и классом важно для взаимодействия с бэкенд-системами и написания качественного кода. Это фундаментальные концепции объектно-ориентированного программирования.

Основное отличие

Класс — это конкретная реализация, шаблон для создания объектов. Интерфейс — это контракт (соглашение), который определяет, какие методы должны быть реализованы.

Определение и синтаксис

Класс:

public class Animal
{
    public string Name { get; set; }
    
    public virtual void Speak()
    {
        Console.WriteLine("Some sound");
    }
    
    public void Move()
    {
        Console.WriteLine("Moving");
    }
}

Интерфейс:

public interface IAnimal
{
    string Name { get; set; }  // Свойство
    void Speak();              // Метод без реализации
    void Move();               // Только сигнатуры
}

Ключевые отличия

ПараметрКлассИнтерфейс
РеализацияСодержит код методовТолько сигнатуры (C# 8+: default реализация)
СостояниеМожет иметь поля (fields)Только свойства (properties)
КонструкторЕсть конструторыНет конструкторов
Инстанцированиеnew MyClass()Нельзя создать напрямую
НаследованиеОдин класс (single inheritance)Несколько интерфейсов
Модификаторы доступаpublic, private, protectedПо умолчанию public (members)
ИспользованиеДля поведения и состоянияДля определения контракта

Наследование и реализация интерфейсов

Класс наследует класс (single inheritance):

public class Dog : Animal  // Наследование (:)
{
    public override void Speak()  // Переопределение
    {
        Console.WriteLine("Woof!");
    }
}

Класс реализует интерфейс:

public class Dog : IAnimal  // Реализация интерфейса (:)
{
    public string Name { get; set; }
    
    public void Speak()  // Обязательно реализовать!
    {
        Console.WriteLine("Woof!");
    }
    
    public void Move()
    {
        Console.WriteLine("Running on four legs");
    }
}

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

public interface IRunnable
{
    void Run();
}

public interface ISwimmable
{
    void Swim();
}

// Класс может реализовать несколько интерфейсов
public class Duck : IAnimal, IRunnable, ISwimmable
{
    public string Name { get; set; }
    
    public void Speak() { Console.WriteLine("Quack!"); }
    public void Move() { }
    public void Run() { Console.WriteLine("Duck running"); }
    public void Swim() { Console.WriteLine("Duck swimming"); }
}

Состояние и поля

Класс может хранить состояние:

public class BankAccount
{
    private decimal balance;  // Приватное поле (состояние)
    public string AccountNumber { get; set; }  // Свойство
    
    public void Deposit(decimal amount)
    {
        balance += amount;  // Изменяем состояние
    }
    
    public decimal GetBalance()
    {
        return balance;
    }
}

Интерфейс только определяет контракт:

public interface IAccount
{
    string AccountNumber { get; set; }
    void Deposit(decimal amount);
    decimal GetBalance();
    // Нет полей, только методы и свойства
}

Практический пример: система логирования

Интерфейс (контракт):

public interface ILogger
{
    void Log(string message);
    void Error(string message);
}

Реализации (разные классы):

public class ConsoleLogger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine($"[LOG] {message}");
    }
    
    public void Error(string message)
    {
        Console.WriteLine($"[ERROR] {message}");
    }
}

public class FileLogger : ILogger
{
    private string filePath = "log.txt";
    
    public void Log(string message)
    {
        File.AppendAllText(filePath, $"[LOG] {message}\n");
    }
    
    public void Error(string message)
    {
        File.AppendAllText(filePath, $"[ERROR] {message}\n");
    }
}

public class DatabaseLogger : ILogger
{
    public void Log(string message) { /* сохранить в БД */ }
    public void Error(string message) { /* сохранить в БД */ }
}

Использование (зависимость от интерфейса, не от реализации):

public class Application
{
    private ILogger logger;
    
    public Application(ILogger logger)  // Dependency Injection
    {
        this.logger = logger;  // Можно передать любую реализацию
    }
    
    public void Run()
    {
        logger.Log("Application started");  // Не важно, какая реализация
        logger.Error("Something went wrong");
    }
}

// Использование
var consoleLogger = new ConsoleLogger();
var app = new Application(consoleLogger);
app.Run();

// Легко переключиться на файл
var fileLogger = new FileLogger();
var app2 = new Application(fileLogger);  // Один код, другая реализация!

C# 8.0+: Default interface members

С C# 8.0 интерфейсы могут иметь реализацию по умолчанию:

public interface IPrinter
{
    void Print() { Console.WriteLine("Default print"); }  // Реализация!
}

public class MyPrinter : IPrinter
{
    // Может использовать default реализацию или переопределить
    public void Print() { Console.WriteLine("Custom print"); }
}

Когда что использовать

Используйте классы, когда:

  • Нужно хранить состояние (поля, данные)
  • Нужна иерархия наследования
  • Нужны конструкторы для инициализации
  • Нужна конкретная реализация

Используйте интерфейсы, когда:

  • Хочется определить контракт (что должен делать объект)
  • Нужна множественная реализация
  • Хочется слабую связанность (loose coupling)
  • Нужна dependency injection
  • Несколько неродственных классов должны иметь одинаковые методы

SOLID принцип: Dependency Inversion

// ❌ Плохо: зависит от конкретной реализации
public class OrderProcessor
{
    private EmailService emailService = new EmailService();  // Прямая зависимость
    
    public void ProcessOrder(Order order)
    {
        // ...
        emailService.Send("Order processed");
    }
}

// ✅ Хорошо: зависит от интерфейса
public class OrderProcessor
{
    private INotificationService notificationService;  // Интерфейс
    
    public OrderProcessor(INotificationService service)  // Inject
    {
        notificationService = service;
    }
    
    public void ProcessOrder(Order order)
    {
        // ...
        notificationService.Notify("Order processed");  // Не важно какая реализация
    }
}

Практический совет для Data Scientist

Специалист по данным не часто пишет на C#, но иногда нужно интегрировать ML модель в .NET приложение. Интерфейсы используют для:

public interface IModelPredictor
{
    Prediction Predict(InputData data);
    void Train(TrainingData data);
}

public class MLModelAdapter : IModelPredictor
{
    private readonly PythonEngine pythonEngine;  // Вызывает Python
    
    public Prediction Predict(InputData data)
    {
        // Отправляем данные в Python модель
        return pythonEngine.RunModel(data);
    }
    
    public void Train(TrainingData data)
    {
        pythonEngine.Train(data);
    }
}

Итого: Классы — это конкретные объекты с состоянием и поведением, интерфейсы — это контракты, которые определяют только поведение. Интерфейсы обеспечивают гибкость и слабую связанность в коде.

В чем разница между интерфейсом и классом в C#? | PrepBro