Что такое полиморфизм в объектно-ориентированном программировании?

Ответ

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

Суть: Один интерфейс — множество реализаций. Это позволяет писать более гибкий и расширяемый код.

Основные виды полиморфизма:

  1. Полиморфизм подтипов (на основе наследования): Самый распространённый вид. Метод базового класса переопределяется в дочерних классах.
  2. Параметрический полиморфизм (дженерики/шаблоны): Класс или метод может работать с разными типами данных (например, List<T> в Java).
  3. Ad-hoc полиморфизм (перегрузка методов): Несколько методов с одним именем, но разными параметрами в одном классе.

Практический пример на Java (полиморфизм подтипов):

// Базовый интерфейс (контракт)
interface NotificationSender {
    void send(String message);
}

// Конкретные реализации
class EmailSender implements NotificationSender {
    @Override
    public void send(String message) {
        System.out.println("Sending email: " + message);
    }
}

class SmsSender implements NotificationSender {
    @Override
    public void send(String message) {
        System.out.println("Sending SMS: " + message);
    }
}

// Клиентский код, использующий полиморфизм
public class NotificationService {
    public void notifyUser(NotificationSender sender, String msg) {
        // Не важно, какой именно sender передан. Главное — он реализует send().
        sender.send(msg);
    }

    public static void main(String[] args) {
        NotificationService service = new NotificationService();
        service.notifyUser(new EmailSender(), "Hello via Email!");
        service.notifyUser(new SmsSender(), "Hello via SMS!");
    }
}

Преимущества:

  • Снижение связанности: Клиентский код зависит от абстракции (интерфейса), а не от конкретных классов.
  • Упрощение расширения: Чтобы добавить новый способ отправки (например, PushSender), не нужно менять код NotificationService.
  • Повторное использование кода: Общая логика работы с уведомлениями вынесена в один метод.

Ответ 18+ 🔞

А, полиморфизм, говоришь? Ну это ж, блядь, классика, ёпта! Представь себе, сидит такой один чувак, у него есть одна кнопка, одна, сука, хуй с горы. И он этой кнопкой может и телевизор включить, и чайник, и музыку громче сделать, и свет вырубить. Вот это и есть полиморфизм, блядь! Одна хрень, а делает — овердохуища всего разного, в зависимости от того, на какую, сука, железяку ты её нацелил.

Суть-то проще пареной репы: один рот, а кричать можно «Муму!», «Хлеба!» или «Да похуй!» — это и есть разные реализации, блядь.

Виды его, этого полиморфизма:

  1. Наследственный, блядь (подтипов). Это когда сын вроде как на отца похож, а делает всё наоборот, сука. Метод один, а внутри — пиздец какой разный код. Папа говорит «Иди учись», а сын уже «Иду в армию» или «Иду бухать» — метод go() один, а результат, блядь, волнение ебать.
  2. Параметрический (дженерики). Это как универсальная отвёртка, блядь. Одна хуйня, а болты и винты, и шурупы, и гайки — все закрутит. List<T>, где T — это хоть строка, хоть число, хоть твоя старая тапочка.
  3. Ad-hoc (перегрузка). Это когда у тебя один сосед Петя, но он и сантехник Петя, и алкаш Петя, и должник Петя. Смотришь на него по-разному, блядь, в зависимости от ситуации. Метод add(2, 2) и add("Привет, ", "олень") — оба складывают, но пиздец как по-разному.

Вот смотри, как это в коде выглядит, на примере доставки вестей, блядь:

// Вот общий контракт, договорённость, блядь. Все, кто его подписал, обязуются доставлять послания.
interface Гонец {
    void доставитьВесть(String весть);
}

// Конкретные ребята, которые контракт подписали
class ПочтовыйГолубь implements Гонец {
    @Override
    public void доставитьВесть(String весть) {
        System.out.println("Гу-гу! В клюве несу записку: " + весть); // Клювом, блядь
    }
}

class Телеграфист implements Гонец {
    @Override
    public void доставитьВесть(String весть) {
        System.out.println("Типа-типа-типа! По проводам: " + весть); // По проводам, сука
    }
}

// А вот главный начальник, которому похуй, КАК доставить. Его дело — приказать.
public class Царь {
    public void оповеститьНарод(Гонец гонец, String указ) {
        // А вот тут магия, блядь! Ему всё равно, голубь перед ним или телеграфист.
        // Лишь бы метод `доставитьВесть()` был. А уж КАК — это их проблемы.
        гонец.доставитьВесть(указ);
    }

    public static void main(String[] args) {
        Царь батюшка = new Царь();
        батюшка.оповеститьНарод(new ПочтовыйГолубь(), "Завтра все на сенокос, блядь!");
        батюшка.оповеститьНарод(new Телеграфист(), "А кто не явится — того в Сибирь!");
    }
}

И в чём, сука, профит-то?

  • Царь не парится. Ему не нужно знать про голубиные перья и телеграфные столбы. Сказал «оповестить» — и похуй. Снижение связанности, ёпта.
  • Завтра изобретут радио. И что? Добавим класс ДикторРадио, который тоже Гонец. И Царь сможет им пользоваться, БЕЗ ИЗМЕНЕНИЯ СВОЕГО КОДА! Расширяемость, блядь.
  • Код оповеститьНарод один. И для голубя, и для телеги, и для радио. Не нужно плодить кучу методов. Повторное использование, ёбана!

Вот и вся магия, блядь. Не так страшен чёрт, как его малюют. Главное — один интерфейс для всех, а там уже каждый ебёт как хочет.