Estou procurando uma maneira boa e limpa de contornar o fato de que o PHP5 ainda não oferece suporte a herança múltipla. Esta é a hierarquia de classes:
Message
- TextMessage
-------- InvitationTextMessage
- EmailMessage
-------- InvitationEmailMessage
Os dois tipos de classes Convite * têm muito em comum; Eu adoraria ter uma classe pai comum, Convite, da qual ambos herdariam. Infelizmente, eles também têm muito em comum com seus ancestrais atuais ... TextMessage e EmailMessage. Desejo clássico de herança múltipla aqui.
Qual é a abordagem mais leve para resolver o problema?
Obrigado!
php
oop
inheritance
Alex Weinstein
fonte
fonte
Respostas:
Alex, na maioria das vezes você precisa de herança múltipla é um sinal de que sua estrutura de objeto está um tanto incorreta. Na situação que você descreveu, vejo que você tem responsabilidade de classe muito ampla. Se Message fizer parte do modelo de negócios do aplicativo, ela não deve se preocupar com a renderização da saída. Em vez disso, você pode dividir a responsabilidade e usar o MessageDispatcher, que envia a mensagem passada usando texto ou backend html. Não sei seu código, mas deixe-me simular desta forma:
Desta forma, você pode adicionar alguma especialização à classe Message:
Observe que MessageDispatcher tomaria a decisão de enviar como HTML ou texto sem formatação, dependendo da
type
propriedade no objeto Message transmitido.Para resumir, a responsabilidade é dividida entre duas classes. A configuração da mensagem é feita na classe InvitationHTMLMessage / InvitationTextMessage e o algoritmo de envio é delegado ao despachante. Isso é chamado de padrão de estratégia, você pode ler mais sobre ele aqui .
fonte
Tracing
(este é apenas um exemplo) onde deseja ter coisas genéricas como depurar em um arquivo, enviar SMS para problemas críticos e assim por diante. Todas as suas turmas são crianças desta classe. Agora, suponha que você queira criar uma classeException
que deva ter essas funções (= filho deTracing
). Esta classe deve ser filha deException
. Como você projeta essas coisas sem herança múltipla? Sim, você sempre pode ter uma solução, mas sempre chegará perto de hackear. E hackear = solução cara a longo prazo. Fim da história.Talvez você possa substituir uma relação 'é-um' por uma relação 'tem-um'? Um convite pode ter uma mensagem, mas não precisa necessariamente 'é uma' mensagem. Um convite fe pode ser confirmado, o que não combina com o modelo de mensagem.
Pesquise por 'composição vs. herança' se precisar saber mais sobre isso.
fonte
Se eu puder citar Phil neste tópico ...
E Chris ....
Achei que ambos tinham links úteis. Mal posso esperar para experimentar características ou talvez alguns mixins ...
fonte
O framework Symfony tem um plugin mixin para isso , você pode querer dar uma olhada - mesmo apenas para ter ideias, se não para usá-lo.
A resposta do "padrão de design" é abstrair a funcionalidade compartilhada em um componente separado e compor no tempo de execução. Pense em uma maneira de abstrair a funcionalidade de convite como uma classe que é associada às suas classes de mensagem de alguma forma diferente de herança.
fonte
Estou usando traits no PHP 5.4 como forma de resolver isso. http://php.net/manual/en/language.oop5.traits.php
Isso permite a herança clássica com extensões, mas também dá a possibilidade de colocar funcionalidades e propriedades comuns em um 'traço'. Como diz o manual:
fonte
Parece que o padrão do decorador pode ser adequado, mas é difícil dizer sem mais detalhes.
fonte
Esta é uma pergunta e uma solução ....
E sobre o mágico _ call (),Métodos _get (), __set ()? Ainda não testei esta solução, mas e se você fizer uma classe multiInherit. Uma variável protegida em uma classe filha pode conter uma matriz de classes para herdar. O construtor na classe de interface múltipla pode criar instâncias de cada uma das classes que estão sendo herdadas e vinculá-las a uma propriedade privada, digamos _ext. O método __call () poderia usar a função method_exists () em cada uma das classes na matriz _ext para localizar o método correto a ser chamado. __get () e __set podem ser usados para localizar propriedades internas, ou se você for um especialista com referências, você pode fazer com que as propriedades da classe filha e as classes herdadas sejam referências aos mesmos dados. A herança múltipla de seu objeto seria transparente para o código que usa esses objetos. Além disso, os objetos internos podem acessar os objetos herdados diretamente se necessário, desde que o array _ext seja indexado pelo nome da classe. Eu imaginei a criação desta superclasse e ainda não a implementei, pois sinto que se funcionar, pode levar ao desenvolvimento de alguns hábitos ruins de programação.
fonte
instanceof
)Tenho algumas perguntas a fazer para esclarecer o que você está fazendo:
1) Seu objeto de mensagem contém apenas uma mensagem, por exemplo, corpo, destinatário, horário de agendamento? 2) O que você pretende fazer com o seu objeto Convite? Ele precisa ser tratado de maneira especial em comparação com uma EmailMessage? 3) Se sim, O QUE há de tão especial nisso? 4) Se for esse o caso, por que os tipos de mensagem precisam ser tratados de maneira diferente para um convite? 5) E se você quiser enviar uma mensagem de boas-vindas ou uma mensagem de OK? Eles também são objetos novos?
Parece que você está tentando combinar muitas funcionalidades em um conjunto de objetos que devem se preocupar apenas em manter o conteúdo de uma mensagem - e não em como deve ser tratado. Para mim, você vê, não há diferença entre um convite ou uma mensagem padrão. Se o convite requer tratamento especial, isso significa lógica do aplicativo e não um tipo de mensagem.
Por exemplo: um sistema que construí tinha um objeto de mensagem base compartilhada que foi estendido para SMS, e-mail e outros tipos de mensagem. No entanto: não foram estendidas mais - uma mensagem de convite era simplesmente um texto predefinido a ser enviado por meio de uma mensagem do tipo E-mail. Um aplicativo de convite específico estaria preocupado com a validação e outros requisitos para um convite. Afinal, tudo o que você deseja fazer é enviar a mensagem X ao destinatário Y, que deve ser um sistema separado por si só.
fonte
O mesmo problema do Java. Tente usar interfaces com funções abstratas para resolver esse problema
fonte
PHP oferece suporte a interfaces. Essa pode ser uma boa aposta, dependendo de seus casos de uso.
fonte
Que tal uma classe Convite logo abaixo da classe Mensagem?
então a hierarquia vai:
Mensagem
--- Convite
------ TextMessage
------ EmailMessage
E na classe Convite, adicione a funcionalidade que estava em InvitationTextMessage e InvitationEmailMessage.
Eu sei que Convite não é realmente um tipo de Mensagem, é mais uma funcionalidade de Mensagem. Portanto, não tenho certeza se este é um bom design OO ou não.
fonte