Je recherche un moyen efficace et propre 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 parentale commune, Invitation, dont ils hériteraient tous les deux. Malheureusement, ils ont aussi beaucoup en commun avec leurs ancêtres actuels ... TextMessage et EmailMessage. Désir classique d'héritage multiple ici.
Quelle est l'approche la plus légère pour résoudre le problème?
Merci!
php
oop
inheritance
Alex Weinstein
la source
la source
Réponses:
Alex, la plupart du temps, vous avez besoin d'héritage multiple, c'est un signal que la structure de votre 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 Message fait partie du modèle commercial de l'application, il ne doit pas se soucier du rendu de la sortie. Au lieu de cela, vous pouvez diviser la responsabilité et utiliser MessageDispatcher qui envoie le message transmis à l'aide du backend texte ou html. Je ne connais pas votre code, mais laissez-moi le simuler de cette façon:
De cette façon, vous pouvez ajouter une spécialisation à la classe Message:
Notez que MessageDispatcher prendrait la décision d'envoyer au format HTML ou texte brut en fonction de la
type
propriété de l'objet Message transmis.Pour résumer, la responsabilité est partagée entre deux classes. La configuration des messages est effectuée dans la classe InvitationHTMLMessage / InvitationTextMessage et l'algorithme d'envoi est délégué au répartiteur. C'est ce qu'on appelle le modèle de stratégie, vous pouvez en savoir plus ici .
la source
Tracing
(ce n'est qu'un exemple) où vous voulez avoir des choses génériques comme le débogage dans un fichier, envoyer des SMS pour un problème critique et ainsi de suite. Toutes vos classes sont des enfants de cette classe. Supposons maintenant que vous souhaitiez créer une classeException
qui devrait avoir ces fonctions (= enfant deTracing
). Cette classe doit être un enfant deException
. Comment concevoir de telles choses sans héritage multiple? Oui, vous pouvez toujours avoir une solution, mais vous serez toujours proche du piratage. Et le piratage = solution coûteuse à long terme. Fin de l'histoire.Peut-être pouvez-vous remplacer une relation «est-un» par une relation «a-une»? Une invitation peut avoir un message, mais elle n'a pas nécessairement besoin de «est-un» message. Une invitation fe peut être confirmée, ce qui ne va pas bien avec le modèle Message.
Recherchez «composition vs héritage» si vous avez besoin d'en savoir plus à ce sujet.
la source
Si je peux citer Phil dans ce fil ...
Et Chris ...
Je pensais qu'ils avaient tous les deux des liens utiles. J'ai hâte d'essayer des traits ou peut-être des mixins ...
la source
Le framework Symfony a un plugin mixin pour cela , vous voudrez peut-être le vérifier - même juste pour des idées, sinon pour l'utiliser.
La réponse du «modèle de conception» est d'abstraire la fonctionnalité partagée dans un composant séparé et de la composer au moment de l'exécution. Pensez à un moyen d'abstraire la fonctionnalité Invitation en tant que classe qui est associée à vos classes Message d'une manière autre que l'héritage.
la source
J'utilise les traits de PHP 5.4 pour résoudre ce problème. http://php.net/manual/en/language.oop5.traits.php
Cela permet un héritage classique avec extend, mais donne également la possibilité de placer des fonctionnalités et des propriétés communes dans un «trait». Comme le dit le manuel:
la source
On dirait que le motif du décorateur peut convenir, mais difficile à dire sans plus de détails.
la source
C'est à la fois une question et une solution ...
Qu'en est-il de la magie _ appel (),Méthodes _get (), __set ()? Je n'ai pas encore testé cette solution mais que faire si vous créez une classe multiInherit. Une variable protégée dans une classe enfant peut contenir un tableau de classes à hériter. Le constructeur de la classe multi-interface 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 () 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 vous êtes un expert avec des références, vous pouvez faire des propriétés de la classe enfant et des classes héritées des références aux mêmes données. L'héritage multiple de votre objet serait transparent pour le code utilisant ces objets. Aussi, les objets internes peuvent accéder directement aux objets hérités si nécessaire tant 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 pense que si cela fonctionne, cela pourrait conduire à développer de mauvaises habitudes de programmation.
la source
instanceof
)J'ai quelques questions à poser pour clarifier ce que vous faites:
1) Votre objet de message contient-il simplement un message, par exemple le corps, le destinataire, l'heure programmée? 2) Que comptez-vous faire avec votre objet Invitation? Doit-il être traité spécialement par rapport à un EmailMessage? 3) Dans l'affirmative, QUELLE EST LA particularité? 4) Si tel est le cas, pourquoi les types de messages doivent-ils être traité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?
Il semble que vous essayez de combiner trop de fonctionnalités dans un ensemble d'objets qui ne devraient être concernés que par la conservation du contenu d'un message - et non par la façon dont il devrait être géré. Pour moi, vous voyez, il n'y a aucune différence entre une invitation ou un message standard. Si l'invitation nécessite un traitement spécial, cela signifie une 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é qui a été étendu en SMS, e-mail et autres types de messages. Cependant: ceux-ci n'ont pas été étendus davantage - un message d'invitation était simplement un texte prédéfini à envoyer via un message de type Email. Une demande d'invitation spécifique serait concernée par 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.
la source
Même problème que Java. Essayez d'utiliser des interfaces avec des fonctions abstraites pour résoudre ce problème
la source
PHP prend en charge les interfaces. Cela pourrait être un bon pari, en fonction de vos cas d'utilisation.
la source
Que diriez-vous d'une classe Invitation juste en dessous de la classe Message?
donc la hiérarchie va:
Message
--- Invitation
------ TextMessage
------ EmailMessage
Et dans la classe Invitation, ajoutez la fonctionnalité qui était dans InvitationTextMessage et InvitationEmailMessage.
Je sais que l'invitation n'est pas vraiment un type de message, c'est plutôt une fonctionnalité de message. Je ne suis donc pas sûr que ce soit une bonne conception OO ou non.
la source