Estoy buscando una forma buena y limpia de evitar el hecho de que PHP5 todavía no admite la herencia múltiple. Aquí está la jerarquía de clases:
Mensaje
- TextMessage
-------- InvitationTextMessage
- EmailMessage
-------- InvitationEmailMessage
Los dos tipos de clases de Invitación * tienen mucho en común; Me encantaría tener una clase de padres común, Invitación, de la que ambos heredarían. Desafortunadamente, también tienen mucho en común con sus antepasados actuales ... TextMessage y EmailMessage. Deseo clásico de herencia múltiple aquí.
¿Cuál es el enfoque más ligero para resolver el problema?
¡Gracias!
php
oop
inheritance
Alex Weinstein
fuente
fuente
Respuestas:
Alex, la mayoría de las veces que necesitas herencia múltiple es una señal de que la estructura de tu objeto es algo incorrecta. En la situación que describiste, veo que tienes una responsabilidad de clase simplemente demasiado amplia. Si Message es parte del modelo de negocio de la aplicación, no debería preocuparse por la presentación de resultados. En su lugar, puede dividir la responsabilidad y usar MessageDispatcher que envía el mensaje transmitido usando texto o backend html. No conozco tu código, pero déjame simularlo de esta manera:
De esta manera puede agregar algo de especialización a la clase de mensaje:
Tenga en cuenta que MessageDispatcher tomaría la decisión de enviar como HTML o texto sin formato dependiendo de la
type
propiedad en el objeto Message que se haya pasado.En resumen, la responsabilidad se divide en dos clases. La configuración del mensaje se realiza en la clase InvitationHTMLMessage / InvitationTextMessage y el algoritmo de envío se delega al despachador. Esto se llama Patrón de estrategia, puede leer más sobre él aquí .
fuente
Tracing
(esto es solo una muestra) donde desea tener cosas genéricas como depurar en un archivo, enviar SMS para problemas críticos, etc. Todas sus clases son hijos de esta clase. Ahora suponga que desea crear una claseException
que debería tener esas funciones (= hijo deTracing
). Esta clase debe ser hija deException
. ¿Cómo se diseña ese material sin herencia múltiple? Sí, siempre puede tener una solución, pero siempre estará cerca de piratear. Y piratería = solución costosa a largo plazo. Fin de la historia.¿Quizás pueda reemplazar una relación 'es-a' con una relación 'tiene-a'? Una invitación puede tener un mensaje, pero no necesariamente tiene que ser un mensaje "es-un". Es posible que se confirme una invitación fe, lo que no va bien con el modelo Mensaje.
Busque 'composición versus herencia' si necesita saber más sobre eso.
fuente
Si puedo citar a Phil en este hilo ...
Y Chris ...
Pensé que ambos tenían enlaces útiles. No puedo esperar para probar rasgos o tal vez algunos mixins ...
fuente
El marco de Symfony tiene un complemento de mezcla para esto , es posible que desee verificarlo, incluso solo para obtener ideas, si no para usarlo.
La respuesta del "patrón de diseño" es abstraer la funcionalidad compartida en un componente separado y componer en tiempo de ejecución. Piense en una forma de abstraer la funcionalidad de Invitación como una clase que se asocia con sus clases de Mensaje de alguna manera que no sea la herencia.
fuente
Estoy usando rasgos en PHP 5.4 como forma de resolver esto. http://php.net/manual/en/language.oop5.traits.php
Esto permite la herencia clásica con extensiones, pero también ofrece la posibilidad de colocar funciones y propiedades comunes en un "rasgo". Como dice el manual:
fuente
Parece que el patrón del decorador puede ser adecuado, pero es difícil saberlo sin más detalles.
fuente
Esto es tanto una pregunta como una solución ...
¿Qué pasa con la llamada mágica _ (),_get (), __set () métodos? Todavía no he probado esta solución, pero ¿qué pasa si crea una clase multiInherit? Una variable protegida en una clase secundaria podría contener una matriz de clases para heredar. El constructor de la clase de interfaz múltiple podría crear instancias de cada una de las clases que se heredan y vincularlas a una propiedad privada, digamos _ext. El método __call () podría usar la función method_exists () en cada una de las clases en la matriz _ext para localizar el método correcto para llamar. __get () y __set podrían usarse para ubicar propiedades internas, o si es un experto con referencias, podría hacer que las propiedades de la clase secundaria y las clases heredadas sean referencias a los mismos datos. La herencia múltiple de su objeto sería transparente para codificar usando esos objetos. También, los objetos internos podrían acceder directamente a los objetos heredados si fuera necesario, siempre que la matriz _ext esté indexada por nombre de clase. He imaginado la creación de esta superclase y aún no la he implementado, ya que creo que si funciona, podría llevar a desarrollar algunos malos hábitos de programación.
fuente
instanceof
)Tengo un par de preguntas para aclarar lo que está haciendo:
1) ¿Su objeto de mensaje solo contiene un mensaje, por ejemplo, cuerpo, destinatario, horario de programación? 2) ¿Qué piensa hacer con su objeto Invitación? ¿Debe tratarse especialmente en comparación con un mensaje de correo electrónico? 3) Si es así, ¿QUÉ tiene de especial? 4) Si ese es el caso, ¿por qué los tipos de mensajes deben manejarse de manera diferente para una invitación? 5) ¿Qué sucede si desea enviar un mensaje de bienvenida o un mensaje OK? ¿También son objetos nuevos?
Suena como si estuvieras intentando combinar demasiada funcionalidad en un conjunto de objetos que solo deberían preocuparse por mantener el contenido de un mensaje, y no cómo debería manejarse. Para mí, verás, no hay diferencia entre una invitación o un mensaje estándar. Si la invitación requiere un tratamiento especial, eso significa lógica de aplicación y no un tipo de mensaje.
Por ejemplo: un sistema que construí tenía un objeto de mensaje base compartido que se extendió a SMS, correo electrónico y otros tipos de mensajes. Sin embargo, estos no se ampliaron más: un mensaje de invitación era simplemente un texto predefinido que se enviaría a través de un mensaje de tipo Correo electrónico. Una solicitud de invitación específica estaría relacionada con la validación y otros requisitos para una invitación. Después de todo, todo lo que quiere hacer es enviar el mensaje X al destinatario Y, que debería ser un sistema discreto por derecho propio.
fuente
Mismo problema que Java. Intente usar interfaces con funciones abstractas para resolver ese problema
fuente
PHP admite interfaces. Esta podría ser una buena apuesta, dependiendo de sus casos de uso.
fuente
¿Qué tal una clase de invitación justo debajo de la clase de mensaje?
entonces la jerarquía va:
Mensaje
--- Invitación
------ Mensaje de texto
------ Mensaje de correo electrónico
Y en la clase de invitación, agregue la funcionalidad que estaba en InvitationTextMessage y InvitationEmailMessage.
Sé que la invitación no es realmente un tipo de mensaje, es más una funcionalidad de mensaje. Así que no estoy seguro de si este es un buen diseño de OO o no.
fuente