Ответ
Полиморфизм (букв. "много форм") — это принцип ООП, который позволяет объектам с одинаковым интерфейсом (типом) вести себя по-разному в зависимости от их конкретной реализации. Код, работающий с базовым типом, автоматически может работать и с любым его производным типом.
В PHP полиморфизм реализуется преимущественно через:
1. Переопределение методов при наследовании
Дочерний класс предоставляет свою конкретную реализацию метода, уже объявленного в родительском классе.
abstract class NotificationSender {
abstract public function send(string $message): void;
}
class EmailSender extends NotificationSender {
public function send(string $message): void {
echo "Отправляем email с текстом: {$message}n";
}
}
class SmsSender extends NotificationSender {
public function send(string $message): void {
echo "Отправляем SMS: {$message}n";
}
}
// Полиморфный вызов
function notifyUser(NotificationSender $sender, string $alert) {
$sender->send($alert); // Неважно, какой именно sender пришёл. Он знает, КАК отправлять.
}
$email = new EmailSender();
$sms = new SmsSender();
notifyUser($email, "Ваш заказ готов!"); // Отправляем email...
notifyUser($sms, "Код подтверждения: 1234"); // Отправляем SMS...
2. Использование интерфейсов
Интерфейс определяет контракт (набор методов), который должны реализовать все классы, его использующие. Это чистейшая форма полиморфизма.
interface LoggerInterface {
public function log(string $level, string $message): void;
}
class FileLogger implements LoggerInterface {
public function log(string $level, string $message): void {
file_put_contents('app.log', "[$level] $messagen", FILE_APPEND);
}
}
class DatabaseLogger implements LoggerInterface {
public function log(string $level, string $message): void {
// Вставка записи $level, $message в таблицу логов
echo "[DB LOG] [$level] $messagen";
}
}
class Application {
private LoggerInterface $logger;
public function __construct(LoggerInterface $logger) {
$this->logger = $logger; // Принимаем ЛЮБОЙ логгер, реализующий интерфейс
}
public function run() {
$this->logger->log('INFO', 'Приложение запущено');
// ... бизнес-логика
$this->logger->log('ERROR', 'Что-то пошло не так');
}
}
// Запуск с разными логгерами
$appWithFileLog = new Application(new FileLogger());
$appWithDbLog = new Application(new DatabaseLogger());
$appWithFileLog->run(); // Пишет в файл
$appWithDbLog->run(); // Пишет в базу данных
Суть полиморфизма: программа оперирует абстракциями (NotificationSender, LoggerInterface), а конкретное поведение определяется во время выполнения (runtime) типом реального объекта (EmailSender, DatabaseLogger). Это делает систему гибкой, расширяемой и легко тестируемой (зависимости можно подменять).
Ответ 18+ 🔞
Да ты посмотри, какая хитрая жопа этот полиморфизм! В переводе — «много форм», но по сути это просто умение одной и той же хуйни работать по-разному, в зависимости от того, какую конкретно подсунули реализацию. Если код написан под общий тип, он спокойно сожрёт любой дочерний класс, и даже не поперхнётся.
В PHP это делается в основном двумя путями, и оба — овердохуища удобные.
1. Когда наследники переписывают родительские методы
Представь, есть у тебя абстрактный класс-родитель, который говорит: «Вот метод send(), но как его делать — я, блядь, не знаю». А его дети уже конкретно решают, как именно отправлять сообщение: по email или SMS.
abstract class NotificationSender {
abstract public function send(string $message): void;
}
class EmailSender extends NotificationSender {
public function send(string $message): void {
echo "Отправляем email с текстом: {$message}n";
}
}
class SmsSender extends NotificationSender {
public function send(string $message): void {
echo "Отправляем SMS: {$message}n";
}
}
// А вот тут и начинается магия, ёпта
function notifyUser(NotificationSender $sender, string $alert) {
$sender->send($alert); // Похуй, что за sender пришёл. Он сам знает, что делать.
}
$email = new EmailSender();
$sms = new SmsSender();
notifyUser($email, "Ваш заказ готов!"); // Отправляем email...
notifyUser($sms, "Код подтверждения: 1234"); // Отправляем SMS...
Видишь? Функция notifyUser работает с абстракцией NotificationSender, а на деле туда можно запихнуть что угодно, лишь бы у этого «чего угодно» был метод send(). И оно само разберётся.
2. Через интерфейсы — чистейшая форма полиморфизма
Тут вообще доверия ебать ноль, но зато строго. Интерфейс — это контракт. Подписался на него — будь добр, реализуй все указанные методы. А дальше хоть в файл пиши, хоть в базу, хоть на Луну сигнал отправляй.
interface LoggerInterface {
public function log(string $level, string $message): void;
}
class FileLogger implements LoggerInterface {
public function log(string $level, string $message): void {
file_put_contents('app.log', "[$level] $messagen", FILE_APPEND);
}
}
class DatabaseLogger implements LoggerInterface {
public function log(string $level, string $message): void {
// Вставка записи $level, $message в таблицу логов
echo "[DB LOG] [$level] $messagen";
}
}
class Application {
private LoggerInterface $logger;
public function __construct(LoggerInterface $logger) {
$this->logger = $logger; // Принимаем ЛЮБОЙ логгер, который подписал контракт
}
public function run() {
$this->logger->log('INFO', 'Приложение запущено');
// ... бизнес-логика
$this->logger->log('ERROR', 'Что-то пошло не так');
}
}
// Запускаем приложение с разными логгерами
$appWithFileLog = new Application(new FileLogger());
$appWithDbLog = new Application(new DatabaseLogger());
$appWithFileLog->run(); // Пишет в файл
$appWithDbLog->run(); // Пишет в базу данных
Соль в чём: весь твой код завязан на абстракции (LoggerInterface), а не на конкретных классах. Это как если бы ты говорил: «Мне нужен кто-то, кто умеет логировать». А уж придёт ли тебе файловый логгер, или логгер в базу, или вообще логгер, который кричит в окно — тебе похуй. Главное, чтобы метод log() был. Система становится гибкой, её легко расширять и тестировать, потому что зависимости можно подменять, как перчатки. Вот и вся магия, ебать копать.
Видео-ответы
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶