Héritage Multiple en PHP

je cherche une bonne façon de contourner le fait que PHP5 ne supporte toujours pas l'héritage multiple. Voici la hiérarchie de classe:

Message

-- TextMessage

-------- InvitationTextMessage

-- EmailMessage

-------- InvitationEmailMessage

les deux types d'invitations* classes ont beaucoup en commun; j'aimerais avoir une classe de parents commune, Invitation, dont ils hériteraient tous les deux. Malheureusement, ils ont aussi beaucoup en commun avec leurs ancêtres... TextMessage et EmailMessage. Le désir classique d'héritage multiple ici.

Quelle est l'approche la plus légère pour résoudre le problème?

Merci!

95
demandé sur Alex Weinstein 2008-09-18 12:40:19

11 réponses

Alex, la plupart du temps vous avez besoin d'héritage multiple est un signal votre structure d'objet est quelque peu incorrecte. Dans la situation que vous avez décrite, je vois que vous avez une responsabilité de classe tout simplement trop large. Si le Message fait partie du modèle d'affaires d'application, il ne devrait pas prendre soin de rendre la sortie. Au lieu de cela, vous pouvez partager la responsabilité et utiliser MessageDispatcher qui envoie le Message passé en utilisant le backend texte ou html. Je ne connais pas votre code, mais laissez-moi le simuler de cette façon:

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

de cette façon, vous pouvez ajouter une certaine spécialisation à la classe de 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);

notez que MessageDispatcher prendrait une décision quant à savoir s'il faut envoyer en HTML ou en texte simple en fonction de la propriété type dans L'objet Message passé.

// 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");
    }
}

en résumé, la responsabilité est répartie entre deux classes. La configuration des messages se fait dans la classe InvitationHTMLMessage/InvitationTextMessage, et l'algorithme d'envoi est délégué au répartiteur. Ceci est appelé modèle de stratégie, vous pouvez lire plus sur le ici .

141
répondu Michał Rudnicki 2008-09-18 11:13:24

peut-être Pouvez-vous remplacer une relation "est-a" par une relation "a-a"? Une Invitation peut avoir un Message, mais elle n'a pas nécessairement besoin d'un message "est-a". Une Invitation F. E. peut-être confirmé, ce qui ne va pas bien avec le modèle de Message.

cherchez 'composition vs. inheritance' si vous avez besoin d'en savoir plus à ce sujet.

14
répondu Matthias Kestenholz 2008-09-18 08:45:27

si je peux citer Phil dans ce fil ...

PHP, comme Java, ne supporte pas les héritages multiples.

venant en PHP 5.4 sera traits qui tentent de fournir une solution pour ce problème.

dans l'intervalle, vous seriez mieux de repenser votre conception de classe. Vous peut implémenter plusieurs interfaces si vous êtes après une extension de L'API à vos classes.

Et Chris....

PHP ne supporte pas vraiment les héritages multiples, mais il y a certains (somewhat messy) des façons de le mettre en œuvre. Voir cette URL pour certains exemples:

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

pensait qu'ils avaient tous les deux des liens utiles. Ne peut pas attendre pour essayer des traits ou peut-être des mixins...

7
répondu Simon East 2017-05-23 12:34:17

le cadre Symfony a un plugin mixin pour ce , vous pourriez vouloir le vérifier -- même juste pour des idées, si de ne pas l'utiliser.

la réponse "design pattern" est d'abstraire la fonctionnalité partagée en un composant séparé, et de composer à l'exécution. Pensez à une façon d'abstraire la fonctionnalité D'Invitation comme une classe qui est associée à vos classes de messages d'une manière autre que l'héritage.

6
répondu joelhardi 2008-09-18 08:43:24

cela ressemble au motif décorateur peut être approprié, mais difficile à dire sans plus de détails.

3
répondu danio 2008-09-18 08:43:10

C'est à la fois une question et une solution....

en Ce qui concerne l'magique _ call(), _get(), __set ()? Je n'ai pas encore testé cette solution mais que faire si vous faites une multiInherit classe. Protégé variable dans une classe enfant pourraient contenir un tableau de classes héritent. Le constructeur dans la classe multi-interface pourrait créer des instances de chacune des classes héritées et les relier à une propriété privée, disons _ext. Le _La méthode _call() pourrait utiliser la fonction method_exists () sur chacune des classes du tableau _ext pour localiser la méthode correcte à appeler. __get () et _ _ set pourraient être utilisés pour localiser les propriétés internes, ou si votre expert avec des références vous pouvez faire les propriétés de la classe enfant et les classes héritées être des références aux mêmes données. L'héritage multiple de votre objet serait transparent pour coder en utilisant ces objets. De plus, les objets internes peuvent accéder directement aux objets hérités. si nécessaire, aussi longtemps que le tableau _ext est indexé par nom de classe. J'ai envisagé de créer cette super-classe et je ne l'ai pas encore implémentée car je sens que si elle fonctionne, elle pourrait conduire à développer de mauvaises habitudes de programmation.

3
répondu Ralph Ritoch 2010-10-20 07:52:24

j'utilise des traits en PHP 5.4 comme moyen de résoudre ceci. http://php.net/manual/en/language.oop5.traits.php

cela permet un héritage classique avec des extensions, mais donne aussi la possibilité de placer des fonctionnalités et des propriétés communes dans un "trait". Comme le dit le manuel:

Traits est un mécanisme pour la réutilisation de code dans les langues d'héritage simple telles que PHP. Un Trait vise à réduire certains limites de l'héritage unique en permettant à un développeur de réutiliser des ensembles de méthodes librement dans plusieurs classes indépendantes vivant dans des hiérarchies de classes différentes.

3
répondu MatthewPearson 2012-11-15 12:02:11

j'ai quelques questions à poser pour clarifier ce que vous faites:

1) est-ce que votre message objet juste contient un message par exemple corps, destinataire, horaire? 2) que comptez-vous faire de votre objet D'Invitation? Doit-il être traité de manière spécifique par rapport à un message? 3) dans l'affirmative, QU'y a-t-il de si spécial? 4) Si c'est le cas, pourquoi les types de messages doivent-ils être traités différemment pour une invitation? 5) et si vous voulez envoyer un message de bienvenue ou un message OK? Sont-ils de nouveaux objets?

il semble que vous essayez de combiner trop de fonctionnalité dans un ensemble d'objets qui ne devraient être concernés par la tenue d'un contenu de message - et non pas comment il devrait être manipulé. Pour moi, vous voyez, il n'y a pas de différence entre une invitation ou un message standard. Si l'invitation nécessite un traitement spécial, cela signifie logique d'application et non un type de message.

par exemple: un système que j'ai construit avait un objet de message de base partagée qui a été étendu dans SMS, Email, et d'autres types de message. Cependant: ces messages n'ont pas été étendus davantage - un message d'invitation était simplement un texte prédéfini à envoyer par un message de type E-Mail. Une demande d'Invitation spécifique porterait sur la validation et d'autres exigences pour une invitation. Après tout, tout ce que vous voulez faire est d'envoyer le message X au destinataire Y qui devrait être un système discret à part entière.

1
répondu 2008-09-18 14:13:19

même problème que Java. Essayez d'utiliser des interfaces avec des fonctions abstraites pour résoudre ce problème

0
répondu DeeCee 2008-09-18 08:45:27

PHP supporte les interfaces. Cela pourrait être un bon pari, selon vos cas d'utilisation.

0
répondu Cheekysoft 2008-09-23 17:23:08

Que Diriez-vous d'une classe Invitation juste en dessous de la classe Message?

ainsi va la hiérarchie:

Message

--- Invitation

------ TextMessage

------ EmailMessage

et dans la classe Invitation, ajouter la fonctionnalité qui était dans InvitationTextMessage et InvitationEmailMessage.

Je sais que L'Invitation n'est pas vraiment type de Message, c'est plus une fonctionnalité de Message. Donc je ne suis pas sûr que ce soit un bon design OO ou pas.

-1
répondu nube 2012-05-23 21:02:12