Ответ
Интерфейс используется для определения контракта (публичного API), который должны реализовать классы. Это ключевой инструмент для проектирования гибких и поддерживаемых систем.
Основные случаи применения:
-
Определение полиморфного поведения. Несколько классов могут по-разному реализовать один интерфейс.
interface PaymentProcessor { void processPayment(BigDecimal amount); } class CreditCardProcessor implements PaymentProcessor { /*...*/ } class PayPalProcessor implements PaymentProcessor { /*...*/ } - Соблюдение принципа инверсии зависимостей (DIP). Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракций (интерфейсов).
- Создание слабосвязанной архитектуры. Код зависит от интерфейса, а не от конкретной реализации, что упрощает замену и тестирование (например, внедрение мок-объектов в unit-тестах).
- Моделирование различных ролей объекта. Класс может реализовывать несколько интерфейсов.
class Smartphone implements Camera, Phone, GPSNavigator { /*...*/ } - Предоставление API для библиотек или фреймворков. Позволяет клиентам предоставлять свою реализацию (стратегия, наблюдатель).
Интерфейс vs. Абстрактный класс:
- Используйте интерфейс, чтобы определить контракт для несвязанных классов.
- Используйте абстрактный класс, чтобы предоставить общую базовую реализацию для родственных классов.
Ответ 18+ 🔞
А, интерфейсы, ёпта! Ну, это как договор, который ты подписываешь, а потом, блядь, выполняешь, иначе тебе пизда. Представь, что ты приходишь в зал — там висит бумажка: «Все, кто тут качается, должны уметь жать лежа и не срать под штангу». Вот это и есть интерфейс GymDude. Ты можешь быть хоть качком, хоть дрыщом — но если зашел, будь добр, контракт исполни.
Зачем это, блядь, нужно, спросишь? Да овердохуища причин!
-
Полиморфизм, или «Одна дырка, а вставлять можно разное». Объявил ты интерфейс
PaymentProcessor— «плати, сука». И пофиг, кто именно платит: кредитка, крипта или мешок картошки. Главное — методprocessPaymentвызвать.interface PaymentProcessor { void processPayment(BigDecimal amount); // Контракт: «Дай денег, блядь» } class CreditCardProcessor implements PaymentProcessor { public void processPayment(BigDecimal amount) { // Тут магия с полосочкой и CVV } } class PotatoBagProcessor implements PaymentProcessor { public void processPayment(BigDecimal amount) { // Взвешиваем мешок, ебать его в сраку } } -
Принцип «Зависеть от абстракций, а не от конкретных мудаков» (DIP). Твой крутой бизнес-логический модуль не должен знать, что там
CreditCardProcessorвнутри гонит. Он знает только абстракцию — интерфейсPaymentProcessor. Захотел поменять платёжку — просто подсунул другую реализацию, и ни один класс не охуел. -
Слабая связность, или «Живи сам и давай жить другим». Код, который использует интерфейс, нихрена не знает о внутренних пиздюлях конкретного класса. Это как договориться «принеси пиво» — тебе похуй, куда человек за ним бежал: в ларёк, на завод или у соседа спиздил. Главное — пиво в руках. Тестировать — вообще сказка: подсовываешь мок-объект, который просто делает
return true, и не надо ебаться с реальной картой. -
Моделирование ролей, или «Я и швец, и жнец, и на хуя-баба яица». Один класс может реализовывать кучу интерфейсов. Смартфон — он и
Camera, иPhone, иBrickForWindowв случае чего.class MySmartphone implements Camera, Phone, GPSNavigator, Paperweight { // Реализуй всё, жопа с ручками! } -
Библиотекам и фреймворкам — чтобы ты, пользователь, мог свою хуйню встроить. Объявили они интерфейс
EventListener— а ты уже свою реализацию пишешь, где при событии «клик» не просто логируется, а запускается ракета. Стратегия, наблюдатель — вся эта архитектурная хуета держится на интерфейсах.
А теперь, блядь, главный вопрос: интерфейс или абстрактный класс?
- Интерфейс — это когда ты говоришь: «ВСЕ, кто хочет быть
Swimmable, ДОЛЖНЫ уметьswim(). Будь ты уткой, дедом Мазаем или кирпичом — плыви, сука». Определяет контракт для кого угодно. - Абстрактный класс — это когда у тебя есть общая родня. Допустим, есть абстрактный класс
Canine(Псовые). У него уже есть реализованные методыbreathe()иshitInTheYard(). А ты от него наследуешьDogиWolfи добавляешь своё: одинbarkAtMailman(), другойeatGrandma(). То есть даёшь общую базу для родственных уёбков.
Короче, интерфейс — это «что делать», а абстрактный класс часто ещё и «как делать часть этого». Выбирай, исходя из того, хочешь ли ты навязать только правила игры или ещё и часть игрового поля с декорациями.