Pergunta

Eu estou procurando um bom, maneira limpa para ir ao redor do fato de que PHP5 ainda não suporta herança múltipla. Aqui está a hierarquia de classes:

Mensagem
- TextMessage
-------- InvitationTextMessage
- EmailMessage
-------- InvitationEmailMessage

Os dois tipos de convite * classes têm muito em comum; i adoraria ter um pai comum classe, convite, que ambos iria herdar. Infelizmente, eles também têm muito em comum com seus antepassados ??atuais ... TextMessage e EmailMessage. desejo clássica de herança múltipla aqui.

O que é a abordagem mais leve para resolver o problema?

Obrigado!

Foi útil?

Solução

Alex, na maioria das vezes você precisa herança múltipla é um sinal de sua estrutura de objeto é um pouco incorreto. Na situação que você delineou Vejo que você tem a responsabilidade de classe simplesmente demasiado ampla. Se mensagem é parte do modelo de negócios aplicativo, ele não deve tomar cuidado sobre o processamento de saída. Em vez disso, você poderia dividir a responsabilidade e usar MessageDispatcher que envia a mensagem passada usando texto ou html backend. Eu não sei o seu código, mas deixe-me simulá-lo desta maneira:

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

Desta forma, você pode adicionar um pouco de especialização para a classe mensagem:

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

Note que MessageDispatcher iria tomar uma decisão se a enviar como HTML ou texto simples dependendo propriedade type no objeto de mensagem passou.

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

Para resumir, a responsabilidade é dividida entre duas classes. configuração mensagem é feito em sala de aula InvitationHTMLMessage / InvitationTextMessage e envio algoritmo é delegada ao despachante. Isso é chamado de padrão de estratégia, você pode ler mais sobre ele aqui .

Outras dicas

Talvez você pode substituir um 'é-um' relação com um 'tem-a' relação? Um convite pode ter uma mensagem, mas não precisa necessariamente 'é-um' mensagem. Um F. E. convite pode ser confirmado, o que não vai bem em conjunto com o modelo de mensagem.

Pesquise 'herança vs. composição' se você precisa saber mais sobre isso.

Se eu posso citar Phil em esta discussão ...

PHP, como Java, não suporta herança múltipla.

Chegando em PHP 5.4 será características que tentam fornecer uma solução para este problema.

Entretanto, você seria melhor repensar seu projeto de classe. Vocês pode implementar várias interfaces se você estiver após uma API estendida para suas classes.

E Chris ....

PHP realmente não suporta herança múltipla, mas há alguns (Um pouco bagunçado) maneiras de implementá-lo. Confira esta URL para alguns exemplos:

http://www.jasny.net/articles/ how-i-php-de múltipla herança /

O pensamento que ambos tinham ligações úteis. Mal posso esperar para experimentar traços ou talvez alguns mixins ...

O framework Symfony tem um mixin plugin para isso , você pode querer verificá-la -. mesmo apenas para idéias, se não usá-lo

A resposta "padrão de design" é abstrair a funcionalidade compartilhada em um componente separado, e compor em tempo de execução. Pense em uma maneira de abstrair a funcionalidade do convite como uma classe que fica associado com suas classes Mensagem de alguma forma diferente de herança.

Eu estou usando traços em PHP 5.4 como a maneira de resolver isso. http://php.net/manual/en/language.oop5.traits.php

Isto permite a herança clássico com estende-se, mas também dá a possível colocação de funcionalidade e propriedades em comum um 'traço'. Como diz o manual:

Traços é um mecanismo para a reutilização de código em linguagens de herança simples, como PHP. Um Trait se destina a reduzir algumas limitações de herança única, permitindo que um desenvolvedor para conjuntos de reutilização de métodos livremente em várias classes independentes que vivem em diferentes hierarquias de classe.

Parece que o decorador padrão pode ser adequado, mas difícil dizer, sem mais detalhes .

Isto é tanto uma questão e uma solução ....

E o mágico _ call (), _get (), __set () métodos? Eu ainda não testei essa solução, mas o que se você fizer uma classe multiInherit. Uma variável protegido em uma classe criança pode conter uma variedade de classes para herdar. O construtor da classe multi-Interface pode criar instâncias de cada uma das classes que estão sendo herdadas e ligá-los a uma propriedade privada, dizem _ext. O método __call () pode utilizar a função de () method_exists em cada uma das classes na matriz _ext para localizar o método correcto a chamada. __get () e __set poderia ser usado para localizar propriedades internas, ou se o seu um perito com referências que você poderia fazer as propriedades da classe infantil e as classes herdadas ser referências para os mesmos dados. A herança múltipla de seu objeto seria transparente para o código usando esses objetos. Além disso, objetos internos poderia acessar os objetos herdados diretamente, se necessário, desde que a matriz _ext é indexado pelo nome da classe. Eu previ criação deste super-classe e ainda não implementaram-lo como eu sinto que, se ele funciona do que poderia levar ao desenvolvimento de alguns variar maus hábitos de programação.

Eu tenho um par de perguntas a fazer para esclarecer o que você está fazendo:

1) Será que o seu objeto de mensagem apenas conter uma mensagem de exemplo corpo, destinatário, o tempo previsto? 2) O que você pretende fazer com o seu objeto convite? Será que ela precisa ser tratada especialmente em comparação com uma EmailMessage? 3) Se assim for que há de especial sobre isso? 4) Se for esse o caso, então, por que os tipos de mensagens precisam lidar de forma diferente para um convite? 5) E se você quiser enviar uma mensagem de boas-vindas ou uma mensagem de OK? São eles novos objetos também?

Ele faz som como você está tentando combinar muita funcionalidade em um conjunto de objetos que só deve se preocupar com segurando um conteúdo da mensagem - e não como ele 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, em seguida, que a lógica do aplicativo meio e não um tipo de mensagem.

Por exemplo: um sistema que eu construí tinha um objeto de mensagem base compartilhada que foi estendido para SMS, e-mail e outros tipos de mensagens. No entanto: estes não foram estendidos ainda mais - uma mensagem de convite foi simplesmente texto pré-definido para ser enviado através de uma mensagem do tipo E-mail. A aplicação do convite específico estaria preocupado com a validação e outros requisitos para um convite. Afinal, tudo o que você quer fazer é enviar mensagem X para o destinatário Y, que deve ser um sistema discreto em seu próprio direito.

Mesmo problema como Java. Tente usar interfaces com funções abstratas para resolver esse problema

PHP faz interfaces de apoio. Esta poderia ser uma boa aposta, dependendo de seus casos de uso.

Como sobre uma certa classe convite abaixo da classe Message?

de modo a hierarquia vai:

Mensagem
--- convite
------ TextMessage
------ EmailMessage

E na classe convite, adicionar a funcionalidade que estava em InvitationTextMessage e InvitationEmailMessage.

Eu sei que o convite não é realmente um tipo de mensagem, é mais uma funcionalidade de mensagem. Então, eu não tenho certeza se este é um bom design OO ou não.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top