PHP Çoklu Kalıtım

11 Cevap php

Ben PHP5 hala birden çok devralma desteklemiyor gerçeği etrafında gitmek için iyi, temiz bir yol arıyorum. Burada sınıf hiyerarşisi:

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

Davet * sınıfların iki tür ortak bir şey var; Ben her ikisi de devralan olacağını, ortak bir üst sınıf, Davet isterdim. Ne yazık ki, onlar da ... mevcut ataları ile TextMessage ve EmailMessage ortak bir şey var. Burada çoklu kalıtım için klasik arzusu.

Sorunu çözmek için en hafif yaklaşım nedir?

Teşekkürler!

11 Cevap

Alex, birden çok devralma ihtiyaç zamanların en çok nesne yapısı biraz yanlış bir sinyaldir. Durumda size ben sadece çok geniş bir sınıf sorumluluğumuz var bakın sıraladı. Mesaj uygulama iş modelinin bir parçası ise, bu çıkış render hakkında dikkat çekmek gerekir. Bunun yerine, sorumluluğu bölmek ve metin veya html arka uç kullanarak geçti Mesajı gönderir MessageDispatcher kullanabilirsiniz. Ben kodunuzu biliyorum, ama bana bu şekilde taklit izin vermeyin:

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

Mesaj sınıfı için bazı uzmanlık ekleyebilirsiniz Bu şekilde:

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

MessageDispatcher geçti ileti nesnesi type özelliğine bağlı HTML veya düz metin olarak göndermek isteyip bir karar olacağını unutmayın.

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

O Özetle, sorumluluk iki sınıf arasında paylaştırılır. İleti yapılandırma InvitationHTMLMessage / InvitationTextMessage sınıfta yapılır ve gönderme algoritma memuru delege edilmiştir. Bu Strateji Desen denir, bunu daha fazla okuyabilirsiniz here.

Belki bir 'olan-bir' ilişki ile bir 'olduğu-bir' ilişki değiştirebilirsiniz? Bir Davet Mesaj olabilir, ama mutlaka '-a' mesajı gerekmez. Bir Davet F.E. Mesaj modeli ile birlikte iyi gitmez, hangi teyit olabilir.

Eğer bu konuda daha fazla bilmek gerekiyorsa 'miras vs kompozisyon' için arama.

Symfony framework olan bir mixin plugin for this, bunu kontrol etmek isteyebilirsiniz - hatta sadece fikirler için, kullanmak değilse.

"Tasarım deseni" cevap ayrı bir bileşeni haline soyut paylaşılan işlevsellik ve zamanında oluşturmak. Miras dışında bir şekilde Message sınıflar ile ilişkili alır bir sınıf olarak dışarı Davet işlevselliği dışarı soyut bir yol düşünün.

Bu bir soru ve bir çözüm hem de ....

Ne sihirli hakkında _ call(), _GET (), __ () yöntemleri set? Ben henüz bu çözüm test etmedim ama bir multiInherit sınıf yapmak ne varsa. Bir çocuk sınıfta bir korumalı değişken miras sınıfların bir dizi içerebilir. Multi-arabirim sınıfının yapıcı miras ve özel mülkiyet onları bağlantı ediliyor sınıfların her örneklerini oluşturabilir, _ext söylüyorlar. __ Call () yöntemi çağırmak için doğru yöntemi bulmak için _ext dizideki sınıfların her birinde method_exists () işlevini kullanabilirsiniz. Eğer çocuk sınıfın özelliklerini ve kalıtsal sınıfları yapabilir referansları ile bir uzman aynı verilere referanslar olması halinde __get () ve __ set iç özelliklerini bulmak için kullanılabilir, ya da olabilir. Lütfen nesnenin çoklu kalıtım bu nesneleri kullanarak kod şeffaf olacaktır. Sürece _ext dizi sınıf ismiyle endeksli olarak gerekiyorsa Ayrıca, iç nesneleri doğrudan miras nesneleri erişebilir. Ben bu süper sınıf oluşturarak öngörülen var ve ben bunu geliştirmek için neden olabilir daha çalışır eğer bazı kötü programlama alışkanlıkları farklılık olduğunu hissediyorum henüz uygulanmadı.

decorator pattern daha fazla bilgi olmadan söylemek için uygun, ama zor olabilir gibi geliyor.

Ben Phil alıntı Eğer this thread ...

PHP, Java gibi, birden çok devralma desteklemiyor.

Coming in PHP 5.4 will be traits which attempt to provide a solution to this problem.

In the meantime, you would be best to re-think your class design. You can implement multiple interfaces if you're after an extended API to your classes.

Ve Chris ....

PHP doesn't really support multiple inheritance, but there are some (somewhat messy) ways to implement it. Check out this URL for some examples:

http://www.jasny.net/articles/how-i-php-multiple-inheritance/

Ikisi de yararlı bağlantıları vardı sanıyordum. Özellikleri ya da belki bazı Katmalar denemek için sabırsızlanıyorum ...

Ben ne yapıyorsun netleştirmek için sormak için birkaç soru var:

1) Does your message object just contain a message e.g. body, recipient, schedule time? 2) What do you intend to do with your Invitation object? Does it need to be treated specially compared to an EmailMessage? 3) If so WHAT is so special about it? 4) If that is then the case, why do the message types need handling differently for an invitation? 5) What if you want to send a welcome message or an OK message? Are they new objects too?

Bu nasıl işleneceğini değil - ve sadece bir mesaj içeriğini tutan ile ilgili olmalıdır nesneleri bir dizi içine çok fazla işlevselliği birleştiren çalışıyor gibi ses yok. Benim için, bakın, bir davete ya da standart bir mesaj arasında hiçbir fark yoktur. Davetiye özel işlem gerektiriyorsa, o uygulama mantığı ve bir ileti türü anlamına gelir.

Örneğin: inşa edilmiş bir sistem SMS, e-posta, ve diğer mesaj türleri içine uzatıldı paylaşılan temel ileti nesne vardı. Ancak: bu daha uzatılabilir değil - bir davet mesajı sadece tip Email bir mesaj yoluyla gönderilecek metni önceden tanımlanmış oldu. Belirli Davet uygulaması doğrulama ve bir davet için diğer gereksinimleri ile ilgili olacaktır. Tüm bunlardan sonra, yapmak istediğiniz tüm kendi başına ayrı bir sistem olmalı alıcı Y'ye mesaj X gönderilir.

I'm using traits in PHP 5.4 as the way of solving this. http://php.net/manual/en/language.oop5.traits.php

Bu uzanan klasik miras sağlar, ama aynı zamanda bir 'özellik' ortak işlevselliği ve özellikleri yerleştirerek olası verir. Manuel dediği gibi:

Özellikleri PHP gibi tek miras dilinde kod yeniden kullanım için bir mekanizmadır. A Sürekli farklı bir sınıf hiyerarşileri yaşayan birkaç bağımsız sınıflara serbestçe yöntemleri setleri yeniden bir geliştirici sağlayarak tek miras bazı sınırlamaları azaltmak için tasarlanmıştır.

Java gibi aynı sorun. Bu sorunu çözmek için soyut fonksiyonları ile arayüzleri kullanmayı deneyin

PHP desteği arayüzleri yapar. Bu kullanım-duruma bağlı olarak, iyi bir bahis olabilir.

Nasıl sağ Message sınıfının altındaki bir davet sınıfı hakkında?

böylece hiyerarşi gider:

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

Ve Davet sınıfta, InvitationTextMessage ve InvitationEmailMessage oldu işlevsellik eklemek.

O Davet gerçekten Mesaj bir türü değil biliyorum, bu ileti daha bir işlevselliği. Bu iyi OO tasarım olup olmadığını bu yüzden emin değilim.