it-swarm-id.com

Berbagai Warisan dalam PHP

Saya mencari cara yang baik dan bersih untuk mencari tahu fakta bahwa PHP5 masih tidak mendukung banyak pewarisan. Inilah hierarki kelas:

Pesan
-- Pesan teks
-------- InvitationTextMessage
- EmailMessage
-------- InvitationEmailMessage

Dua jenis kelas Invitation * memiliki banyak kesamaan; Saya ingin sekali memiliki kelas orang tua yang sama, Undangan, yang akan mereka warisi. Sayangnya, mereka juga memiliki banyak kesamaan dengan leluhur mereka saat ini ... TextMessage dan EmailMessage. Keinginan klasik untuk multiple inheritance di sini.

Apa pendekatan paling ringan untuk menyelesaikan masalah?

Terima kasih!

97
Alex Weinstein

Alex, sebagian besar waktu Anda membutuhkan pewarisan berganda adalah sinyal struktur objek Anda agak salah. Dalam situasi yang Anda uraikan saya melihat Anda memiliki tanggung jawab kelas terlalu luas. Jika Pesan adalah bagian dari model bisnis aplikasi, itu seharusnya tidak peduli tentang rendering output. Alih-alih, Anda dapat membagi tanggung jawab dan menggunakan MessageDispatcher yang mengirim Pesan yang diteruskan menggunakan teks atau html backend. Saya tidak tahu kode Anda, tetapi izinkan saya mensimulasikannya seperti ini:

$m = new Message();
$m->type = 'text/html';
$m->from = 'John Doe <[email protected]>';
$m->to = 'Random Hacker <[email protected]>';
$m->subject = 'Invitation email';
$m->importBody('invitation.html');

$d = new MessageDispatcher();
$d->dispatch($m);

Dengan cara ini Anda dapat menambahkan beberapa spesialisasi ke kelas Pesan:

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

Perhatikan bahwa MessageDispatcher akan membuat keputusan apakah akan mengirim sebagai HTML atau teks biasa tergantung pada properti type di objek Message yang diteruskan.

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

Singkatnya, tanggung jawab dibagi antara dua kelas. Konfigurasi pesan dilakukan di kelas InvitationHTMLMessage/InvitationTextMessage, dan algoritma pengiriman didelegasikan ke operator. Ini disebut Pola Strategi, Anda dapat membacanya lebih lanjut di sini .

142
Michał Rudnicki

Mungkin Anda bisa mengganti hubungan 'is-a' dengan hubungan 'has-a'? Undangan mungkin memiliki Pesan, tetapi tidak perlu pesan 'is-a'. Undangan f.e. mungkin dikonfirmasi, yang tidak cocok dengan model Pesan.

Cari 'komposisi vs. warisan' jika Anda perlu tahu lebih banyak tentang itu.

14

Jika saya bisa mengutip Phil di tas ini ...

PHP, seperti Java, tidak mendukung multiple inheritance.

Datang dengan PHP 5.4 akan menjadi ciri-ciri yang berupaya memberikan solusi untuk masalah ini .

Sementara itu, Anda sebaiknya memikirkan kembali desain kelas Anda. Anda dapat mengimplementasikan banyak antarmuka jika Anda menginginkan API yang diperluas ke kelas Anda.

Dan Chris ....

PHP tidak benar-benar mendukung multiple inheritance, tetapi ada beberapa (agak berantakan) cara untuk mengimplementasikannya. Lihat URL ini untuk beberapa contoh:

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

Mereka berdua memiliki tautan yang bermanfaat. Tidak sabar untuk mencoba ciri-ciri atau mungkin beberapa mixin ...

9
Simon East

Kerangka kerja Symfony memiliki plugin mixin untuk ini , Anda mungkin ingin memeriksanya - bahkan hanya untuk gagasan, jika tidak menggunakannya.

Jawaban "pola desain" adalah untuk mengabstraksi fungsi bersama menjadi komponen yang terpisah, dan menulis pada saat runtime. Pikirkan cara untuk mengabstraksi fungsionalitas Undangan sebagai kelas yang terkait dengan kelas Pesan Anda dengan cara lain selain pewarisan.

6
joelhardi

Saya menggunakan ciri-ciri dalam PHP 5.4 sebagai cara mengatasi hal ini. http://php.net/manual/en/language.oop5.traits.php

Hal ini memungkinkan untuk pewarisan klasik dengan extends, tetapi juga memberikan kemungkinan menempatkan fungsionalitas dan properti umum ke dalam 'sifat'. Seperti yang tertulis dalam manual:

Ciri adalah mekanisme untuk menggunakan kembali kode dalam bahasa pewarisan tunggal seperti PHP. Trait dimaksudkan untuk mengurangi beberapa batasan pewarisan tunggal dengan memungkinkan pengembang untuk menggunakan kembali set metode secara bebas di beberapa kelas independen yang hidup dalam hierarki kelas yang berbeda.

4
MatthewPearson

Ini adalah pertanyaan dan solusi ....

Bagaimana dengan metode ajaib _panggilan (), _ get (), __set ()? Saya belum menguji solusi ini tetapi bagaimana jika Anda membuat kelas multiInherit. Variabel yang dilindungi dalam kelas anak dapat berisi array kelas untuk diwariskan. Konstruktor di kelas multi-antarmuka dapat membuat instance dari masing-masing kelas yang diwarisi dan menautkannya ke properti pribadi, katakan _ext. Metode __call () dapat menggunakan fungsi method_exists () pada setiap kelas dalam array _ext untuk menemukan metode yang benar untuk dipanggil. __get () dan __set dapat digunakan untuk menemukan properti internal, atau jika ahli Anda dengan referensi, Anda bisa membuat properti dari kelas anak dan kelas yang diwarisi menjadi referensi ke data yang sama. Warisan berganda objek Anda akan transparan untuk kode menggunakan objek-objek tersebut. Juga, objek internal dapat mengakses objek yang diwarisi secara langsung jika diperlukan selama array _ext diindeks oleh nama kelas. Saya telah membayangkan membuat kelas-super ini dan belum mengimplementasikannya karena saya merasa jika itu berhasil maka dapat mengembangkan beberapa kebiasaan pemrograman yang buruk.

3
Ralph Ritoch

Kedengarannya seperti pola dekorator mungkin cocok, tetapi sulit untuk mengatakan tanpa rincian lebih lanjut.

3
danio

Saya punya beberapa pertanyaan untuk diklarifikasi apa yang Anda lakukan:

1) Apakah objek pesan Anda adil berisi pesan, mis. tubuh, penerima, jadwal waktu? 2) Apa yang ingin Anda lakukan dengan objek Undangan Anda? Apakah perlu diperlakukan secara khusus dibandingkan dengan EmailMessage? 3) Jika ya, apa istimewanya? 4) Jika demikian halnya, mengapa jenis pesan perlu ditangani secara berbeda untuk undangan? 5) Bagaimana jika Anda ingin mengirim pesan selamat datang atau pesan OK? Apakah mereka juga benda baru?

Memang terdengar seperti Anda mencoba menggabungkan terlalu banyak fungsi ke dalam satu set objek yang seharusnya hanya berkaitan dengan menyimpan konten pesan - dan bukan bagaimana penanganannya. Bagi saya, Anda lihat, tidak ada perbedaan antara undangan atau pesan standar. Jika undangan memerlukan penanganan khusus, maka itu berarti logika aplikasi dan bukan tipe pesan.

Misalnya: sistem yang saya buat memiliki objek pesan dasar bersama yang diperluas ke SMS, Email, dan jenis pesan lainnya. Namun: ini tidak diperpanjang lebih jauh - pesan undangan hanyalah teks yang telah ditentukan untuk dikirim melalui pesan tipe Email. Aplikasi Undangan khusus akan berkaitan dengan validasi dan persyaratan lain untuk undangan. Lagi pula, semua yang ingin Anda lakukan adalah mengirim pesan X ke penerima Y yang seharusnya merupakan sistem tersendiri.

1
Dave

Masalah yang sama seperti Java. Coba gunakan antarmuka dengan fungsi abstrak untuk menyelesaikan masalah itu

0
DeeCee

PHP mendukung antarmuka. Ini bisa menjadi taruhan yang baik, tergantung pada kasus penggunaan Anda.

0
Cheekysoft