Question

Je cherche un moyen propre et efficace de contourner le fait que PHP5 ne prend toujours pas en charge l'héritage multiple. Voici la hiérarchie des classes:

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

Les deux types de classes Invitation * ont beaucoup en commun; J'adorerais avoir une classe parent commune, Invitation, dont ils hériteraient tous les deux. Malheureusement, ils ont également beaucoup en commun avec leurs ancêtres actuels ... TextMessage et EmailMessage. Désir classique pour l'héritage multiple ici.

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

Merci!

Était-ce utile?

La solution

Alex, la plupart du temps, vous avez besoin d'un héritage multiple, c'est un signe que votre structure d'objet est quelque peu incorrecte. Dans la situation que vous avez décrite, je vois que votre responsabilité de classe est trop large. Si Message fait partie du modèle commercial de l'application, il ne doit pas s'occuper du rendu de la sortie. Au lieu de cela, vous pouvez répartir les responsabilités et utiliser MessageDispatcher qui envoie le message transmis à l'aide d'un fichier texte ou d'un fichier HTML. Je ne connais pas votre code, mais laissez-moi le simuler ainsi:

$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 spécialisation à la classe 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 la décision d'envoyer au format HTML ou texte brut en fonction de la propriété type dans l'objet Message transmis.

// 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 partagée entre deux classes. La configuration du message est effectuée dans la classe InvitationHTMLMessage / InvitationTextMessage et l'algorithme d'envoi est délégué au répartiteur. C’est ce que l’on appelle stratégie, vous pouvez en lire plus à ce sujet ici .

Autres conseils

Peut-être pouvez-vous remplacer une relation "est-une" par une relation "a-une"? Une invitation peut avoir un message, mais il n'est pas nécessaire qu'elle soit un message. Une invitation par exemple peut être confirmé, ce qui ne va pas bien avec le modèle Message.

Recherchez "composition vs héritage" si vous souhaitez en savoir plus à ce sujet.

Si je peux citer Phil dans ce fil ...

  

PHP, comme Java, ne supporte pas l'héritage multiple.

     

Venir en PHP 5.4 sera traits > qui tente de fournir une solution   à ce problème.

     

En attendant, vous feriez mieux de repenser la conception de votre classe. Vous   peut implémenter plusieurs interfaces si vous recherchez une API étendue à   vos cours.

Et Chris ....

  

PHP ne supporte pas vraiment l'héritage multiple, mais il y en a   (un peu brouillon) façons de le mettre en œuvre. Découvrez cette URL pour certains   exemples:

     

http://www.jasny.net/articles/ comment-je-php-multiple-héritage /

Je pensais que tous les deux avaient des liens utiles. J'ai hâte d'essayer des traits ou peut-être des mixins ...

Le cadre Symfony a un plugin de mixage pour cela. , vous voudrez peut-être y jeter un coup d'œil, ne serait-ce que pour des idées, sinon pour l'utiliser.

Le "motif de conception" La solution consiste à résumer la fonctionnalité partagée dans un composant séparé et à composer au moment de l’exécution. Pensez à un moyen de résumer la fonctionnalité d'invitation en tant que classe associée à vos classes Message autrement que par héritage.

J'utilise les traits en PHP 5.4 pour résoudre ce problème. http://php.net/manual/fr/language.oop5.traits.php

Cela permet un héritage classique avec étend, mais permet également de placer des fonctionnalités et des propriétés communes dans un "trait". Comme le dit le manuel:

  

Traits est un mécanisme de réutilisation de code dans des langages à héritage unique tels que PHP. Un trait est destiné à réduire certaines limitations de l'héritage simple en permettant à un développeur de réutiliser librement des ensembles de méthodes dans plusieurs classes indépendantes vivant dans différentes hiérarchies de classes.

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

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

Qu'en est-il des méthodes magiques _ call (), _get (), __set ()? Je n'ai pas encore testé cette solution, mais que se passe-t-il si vous créez une classe multi-héréditaire? Une variable protégée dans une classe enfant peut contenir un tableau de classes à hériter. Le constructeur de la classe multi-interfaces peut créer des instances de chacune des classes héritées et les lier à une propriété privée, par exemple _ext. La méthode __call () peut utiliser la fonction method_exists () sur chacune des classes du tableau _ext pour localiser la méthode correcte à appeler. __get () et __set peuvent être utilisés pour localiser les propriétés internes. Si vous êtes un expert avec des références, vous pouvez définir les propriétés de la classe enfant et des classes héritées avec les mêmes données. L'héritage multiple de votre objet serait transparent pour le code utilisant ces objets. De plus, les objets internes peuvent accéder directement aux objets hérités si nécessaire, à condition que le tableau _ext soit indexé par nom de classe. J'ai envisagé de créer cette super classe et je ne l'ai pas encore mise en œuvre, car je pense que si cela fonctionne, cela pourrait conduire à la création de mauvaises habitudes de programmation.

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

1) Votre objet de message juste contient-il un message, par exemple. corps, destinataire, heure prévue? 2) Qu'avez-vous l'intention de faire avec votre objet Invitation? Doit-il être traité spécialement par rapport à EmailMessage? 3) Si c'est le cas QU'Y A-T-IL de si spécial? 4) Si tel est le cas, pourquoi les types de message doivent-ils être gérés différemment pour une invitation? 5) Que faire si vous souhaitez envoyer un message de bienvenue ou un message OK? Sont-ils aussi de nouveaux objets?

On dirait que vous essayez de combiner trop de fonctionnalités dans un ensemble d’objets qui ne devraient concerner que la conservation du contenu du message - et non la façon dont il devrait être géré. Pour moi, vous voyez, il n'y a pas de différence entre une invitation et un message standard. Si l'invitation nécessite un traitement spécial, il s'agit alors d'une logique d'application et non d'un type de message.

Par exemple: un système que j'ai construit avait un objet de message de base partagé qui a été étendu aux types de message SMS, Email et autres. Cependant, ils n'étaient pas étendus: un message d'invitation consistait simplement en un texte prédéfini à envoyer via un message de type Email. Une application d'invitation spécifique concernerait la validation et d'autres conditions requises 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 distinct à part entière.

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

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

Que diriez-vous d'une classe d'invitation juste en dessous de la classe Message?

ainsi la hiérarchie va:

Message
--- Invitation
------ TextMessage
------ EmailMessage

Et dans la classe Invitation, ajoutez la fonctionnalité qui figurait dans InvitationTextMessage et InvitationEmailMessage.

Je sais que l'invitation n'est pas vraiment un type de message, mais une fonctionnalité de message. Je ne suis donc pas sûr que ce soit une bonne conception OO ou non.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top