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


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

-- TextMessage
-------- InvitationTextMessage
-- EmailMessage
-------- InvitationEmailMessage

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

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

спасибо!

11 95

11 ответов:

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

$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);

таким образом, вы можете добавить некоторую специализацию в класс сообщений:

$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 свойство в переданном объекте сообщения.

// 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, а алгоритм отправки делегируется диспетчеру. Это называется Шаблон стратегии, вы можете прочитать больше об этом здесь.

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

Поиск 'композиция и наследование, если вам нужно знать больше об этом.

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

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

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

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

и Крис....

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

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

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

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

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

звучит как шаблон "декоратор" может быть любой, но трудно сказать без более подробной информации.

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

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

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

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

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

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

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

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

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

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

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

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

иерархия идет так:

--- Приглашение
------ TextMessage
------ EmailMessage

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

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