Множественное наследование в PHP

Я ищу хороший, чистый способ обойти тот факт, что PHP5 по-прежнему не поддерживает множественное наследование. Вот иерархия классов:

Сообщение
— Текстовое сообщение
——– InvitationTextMessage
— Сообщение электронной почты
——– InvitationEmailMessage

У двух типов классов приглашения * есть много общего; я хотел бы иметь общий родительский класс, приглашение, которое они оба наследуют. К сожалению, они также имеют много общего с их нынешними предками … TextMessage и EmailMessage. Классическое желание множественного наследования здесь.

Какой самый легкий подход для решения проблемы?

Благодаря!

Solutions Collecting From Web of "Множественное наследование в PHP"

Алекс, большую часть времени, когда вам нужно множественное наследование, является сигналом, что ваша структура объекта несколько некорректна. В ситуации, которую вы изложили, я вижу, что у вас классовая ответственность слишком широка. Если Message является частью бизнес-модели приложения, он не должен заботиться об рендеринге вывода. Вместо этого вы можете разделить ответственность и использовать MessageDispatcher, который отправляет сообщение, переданное с использованием текстового или html-файла. Я не знаю вашего кода, но позвольте мне смоделировать его так:

 $m = new Message(); $m->type = 'text/html'; $m->from = 'John Doe <jdoe@yahoo.com>'; $m->to = 'Random Hacker <rh@gmail.com>'; $m->subject = 'Invitation email'; $m->importBody('invitation.html'); $d = new MessageDispatcher(); $d->dispatch($m); 

Таким образом, вы можете добавить специализацию в класс Message:

 $htmlIM = new InvitationHTMLMessage(); // html type, subject and body configuration in constructor $textIM = new InvitationTextMessage(); // text type, subject and body configuration in constructor $d = new MessageDispatcher(); $d->dispatch($htmlIM); $d->dispatch($textIM); 

Обратите внимание, что MessageDispatcher будет принимать решение о том, отправлять ли HTML или обычный текст в зависимости от свойства type в переданном объекте Message.

 // in MessageDispatcher class public function dispatch(Message $m) { if ($m->type == 'text/plain') { $this->sendAsText($m); } elseif ($m->type == 'text/html') { $this->sendAsHTML($m); } else { throw new Exception("MIME type {$m->type} not supported"); } } 

Подводя итог, ответственность разделяется между двумя классами. Конфигурация сообщений выполняется в классе InvitationHTMLMessage / InvitationTextMessage, а алгоритм отправки делегируется диспетчеру. Это называется Strategy Pattern, вы можете прочитать об этом здесь .

Может быть, вы можете заменить отношение «is-a» с отношением «has-a»? Приглашение может иметь сообщение, но оно необязательно должно быть сообщено «is-a». Подтверждение приглашения может быть подтверждено, что не очень хорошо сочетается с моделью сообщения.

Найдите «композицию против наследования», если вам нужно больше узнать об этом.

Если я могу процитировать Фила в этой теме …

PHP, как и Java, не поддерживает множественное наследование.

Приход в PHP 5.4 станет чертой, которая пытается обеспечить решение этой проблемы.

В то же время вам лучше всего подумать о своем классе. Вы можете реализовать несколько интерфейсов, если после расширенного API к вашим классам.

И Крис ….

PHP на самом деле не поддерживает множественное наследование, но есть некоторые (несколько грязные) способы его реализации. Проверьте этот URL для некоторых примеров:

http://www.jasny.net/articles/how-i-php-multiple-inheritance/

Думали, что у них обоих были полезные ссылки. Не могу дождаться, чтобы попробовать черты или, может быть, некоторые миксины …

Для этого в Symfony Framework есть плагин mixin , вы можете проверить его – даже для идей, если не использовать его.

Ответ «шаблон дизайна» заключается в абстрагировании общей функциональности в отдельный компонент и составлении во время выполнения. Подумайте о том, как абстрагировать функциональность приглашения как класс, который каким-то образом связан с вашими классами сообщений, чем наследование.

Это и вопрос, и решение.

Как насчет магических методов _ call (), _get (), __set ()? Я еще не тестировал это решение, но что делать, если вы создаете класс multiInherit. Защищенная переменная в дочернем классе может содержать массив классов для наследования. Конструктор в классе multi-interface может создавать экземпляры каждого из наследуемых классов и связывать их с частной собственностью, скажем _ext. Метод __call () может использовать функцию method_exists () для каждого из классов массива _ext для поиска правильного метода для вызова. __get () и __set можно использовать для определения внутренних свойств, или если ваш эксперт со ссылками, вы можете сделать свойства дочернего класса и унаследованных классов ссылками на одни и те же данные. Множественное наследование вашего объекта будет прозрачным для кода с использованием этих объектов. Кроме того, внутренние объекты могут обращаться к унаследованным объектам напрямую, если это необходимо, если массив _ext индексируется по имени класса. Я предвидел создание этого суперкласса и еще не реализовал его, поскольку я чувствую, что если он работает, это может привести к развитию некоторых различных плохих привычек программирования.

Я использую черты в PHP 5.4 как способ решения этого. http://php.net/manual/en/language.oop5.traits.php

Это позволяет классическое наследование с расширением, но также дает возможность поместить общую функциональность и свойства в «черту». Как говорится в руководстве:

Черты – это механизм повторного использования кода в отдельных языках наследования, таких как PHP. Предел предназначен для уменьшения некоторых ограничений одиночного наследования, позволяя разработчику свободно использовать множество методов в нескольких независимых классах, живущих в разных иерархиях классов.

Похоже, что образец декоратора может быть подходящим, но трудно сказать без каких-либо подробностей.

У меня есть несколько вопросов, чтобы попросить разъяснить, что вы делаете:

1) Имеет ли ваш объект сообщения только сообщение, например тело, получатель, время расписания? 2) Что вы намерены делать со своим объектом Invitation? Нужно ли его обрабатывать специально по сравнению с EmailMessage? 3) Если так ЧТО это так особенное? 4) Если это так, почему типы сообщений нуждаются в обработке по-разному для приглашения? 5) Что делать, если вы хотите отправить приветственное сообщение или сообщение OK? Это тоже новые объекты?

Похоже, вы пытаетесь объединить слишком много функций в набор объектов, которые должны быть связаны только с содержанием содержимого сообщения, а не с тем, как его следует обрабатывать. Для меня, видите ли, нет разницы между приглашением или стандартным сообщением. Если приглашение требует специальной обработки, то это означает логику приложения, а не тип сообщения.

Например: система, построенная мной, имела общий объект сообщения, который был расширен в SMS, электронную почту и другие типы сообщений. Однако: они не были расширены дальше – приглашение было просто предопределенным текстом, который должен быть отправлен через сообщение типа Email. Специальное приглашение будет касаться проверки и других требований для приглашения. В конце концов, все, что вы хотите сделать, это отправить сообщение X получателю Y, который должен быть дискретной системой в своем собственном праве.

Такая же проблема, как Java. Попробуйте использовать интерфейсы с абстрактными функциями для решения этой проблемы

PHP поддерживает интерфейсы. Это может быть хорошей ставкой, в зависимости от ваших случаев использования.

Как насчет класса приглашения прямо под классом Message?

поэтому иерархия идет:

Сообщение
— Приглашение
—— Текстовое сообщение
—— Сообщение электронной почты

И в классе приглашения добавьте функциональность, которая была в InvitationTextMessage и InvitationEmailMessage.

Я знаю, что приглашение на самом деле не является типом сообщения, это скорее функциональность Message. Поэтому я не уверен, что это хороший дизайн OO или нет.