Saya sedang mencari cara yang baik dan bersih untuk menghindari fakta bahwa PHP5 masih belum mendukung multiple inheritance. Berikut hierarki kelasnya:
Message
- TextMessage
-------- InvitationTextMessage
- EmailMessage
-------- InvitationEmailMessage
Kedua jenis kelas Undangan * memiliki banyak kesamaan; Saya ingin memiliki kelas orang tua yang sama, Undangan, yang akan mereka warisi dari keduanya. Sayangnya, mereka juga memiliki banyak kesamaan dengan leluhur mereka saat ini ... TextMessage dan EmailMessage. Keinginan klasik untuk mendapatkan banyak warisan di sini.
Apa pendekatan yang paling ringan untuk menyelesaikan masalah ini?
Terima kasih!
php
oop
inheritance
Alex Weinstein
sumber
sumber
Jawaban:
Alex, sebagian besar waktu Anda membutuhkan multiple inheritance adalah sinyal bahwa struktur objek Anda agak salah. Dalam situasi yang Anda uraikan, saya melihat Anda memiliki tanggung jawab kelas yang terlalu luas. Jika Message adalah bagian dari model bisnis aplikasi, Message tidak akan menangani rendering output. Sebagai gantinya, Anda dapat membagi tanggung jawab dan menggunakan MessageDispatcher yang mengirimkan Message yang diteruskan menggunakan backend teks atau html. Saya tidak tahu kode Anda, tetapi biarkan saya mensimulasikannya dengan cara ini:
Dengan cara ini Anda dapat menambahkan beberapa spesialisasi ke kelas Pesan:
Perhatikan bahwa MessageDispatcher akan membuat keputusan apakah akan mengirim sebagai HTML atau teks biasa bergantung pada
type
properti di objek Message yang diteruskan.Singkatnya, tanggung jawab dibagi menjadi dua kelas. Konfigurasi pesan dilakukan di kelas InvitationHTMLMessage / InvitationTextMessage, dan algoritme pengiriman didelegasikan ke dispatcher. Ini disebut Pola Strategi, Anda dapat membaca lebih lanjut di sini .
sumber
Tracing
(ini hanya contoh) di mana Anda ingin memiliki hal-hal umum seperti debug ke dalam file, mengirim SMS untuk masalah kritis, dan sebagainya. Semua kelas Anda adalah anak-anak dari kelas ini. Sekarang misalkan Anda ingin membuat kelasException
yang harus memiliki fungsi tersebut (= anak dariTracing
). Kelas ini harus anak dariException
. Bagaimana Anda mendesain barang seperti itu tanpa banyak warisan? Ya, Anda mungkin selalu memiliki solusi, tetapi Anda akan selalu mendekati peretasan. Dan peretasan = solusi mahal dalam jangka panjang. Akhir dari cerita.Mungkin Anda bisa mengganti relasi 'is-a' dengan relasi 'has-a'? Undangan mungkin memiliki Pesan, tetapi tidak harus berupa pesan 'is-a'. Fitur Undangan mungkin dikonfirmasi, yang tidak cocok dengan model Pesan.
Telusuri 'komposisi vs. warisan' jika Anda ingin tahu lebih banyak tentang itu.
sumber
Jika saya bisa mengutip Phil di utas ini ...
Dan Chris ....
Pikir mereka berdua memiliki tautan yang berguna. Tidak sabar untuk mencoba ciri-ciri atau mungkin beberapa campuran ...
sumber
Kerangka kerja Symfony memiliki plugin mixin untuk ini , Anda mungkin ingin memeriksanya - bahkan hanya untuk ide, jika tidak untuk menggunakannya.
Jawaban "pola desain" adalah mengabstraksi fungsionalitas bersama menjadi komponen terpisah, dan menulis pada waktu proses. Pikirkan tentang cara untuk mengabstraksi fungsionalitas Undangan sebagai kelas yang terkait dengan kelas Message Anda dengan cara lain selain warisan.
sumber
Saya menggunakan ciri-ciri dalam PHP 5.4 sebagai cara untuk menyelesaikannya. http://php.net/manual/en/language.oop5.traits.php
Hal ini memungkinkan pewarisan klasik dengan extends, tetapi juga memberikan kemungkinan untuk menempatkan fungsionalitas dan properti umum ke dalam 'ciri'. Seperti yang dikatakan manual:
sumber
Sepertinya pola dekorator mungkin cocok, tetapi sulit untuk membedakannya tanpa detail lebih lanjut.
sumber
Ini adalah pertanyaan sekaligus solusi ....
Bagaimana dengan panggilan magis (),_get (), __set () metode? Saya belum menguji solusi ini, tetapi bagaimana jika Anda membuat kelas multiInherit. Variabel yang dilindungi dalam kelas anak bisa berisi larik kelas yang akan diturunkan. Konstruktor di kelas multi-antarmuka dapat membuat instance dari setiap kelas yang diwariskan dan menautkannya ke properti pribadi, misalnya _ext. Metode __call () bisa menggunakan fungsi method_exists () pada setiap kelas dalam larik _ext untuk menemukan metode yang benar untuk dipanggil. __get () dan __set dapat digunakan untuk menemukan properti internal, atau jika ahli Anda dengan referensi, Anda dapat membuat properti kelas anak dan kelas yang diwariskan menjadi referensi ke data yang sama. Beberapa pewarisan objek Anda akan transparan untuk kode menggunakan objek tersebut. Juga, objek internal bisa mengakses objek yang diwarisi secara langsung jika diperlukan selama array _ext diindeks dengan nama kelas. Saya telah membayangkan membuat kelas super ini dan belum menerapkannya karena saya merasa jika berhasil daripada itu dapat menyebabkan mengembangkan beberapa kebiasaan pemrograman yang buruk.
sumber
instanceof
)Saya punya beberapa pertanyaan untuk ditanyakan untuk mengklarifikasi apa yang Anda lakukan:
1) Apakah objek pesan Anda adil berisi pesan misalnya badan, penerima, waktu jadwal? 2) Apa yang ingin Anda lakukan dengan objek Undangan Anda? Apakah itu perlu diperlakukan secara khusus dibandingkan dengan EmailMessage? 3) Jika demikian APA yang istimewa tentang itu? 4) Jika demikian, mengapa jenis pesan perlu ditangani secara berbeda untuk undangan? 5) Bagaimana jika Anda ingin mengirim pesan selamat datang atau pesan OK? Apakah itu benda baru juga?
Kedengarannya seperti Anda mencoba menggabungkan terlalu banyak fungsionalitas ke dalam satu set objek yang seharusnya hanya berkaitan dengan penyimpanan konten pesan - dan bukan bagaimana seharusnya menanganinya. Bagi saya, Anda tahu, tidak ada perbedaan antara undangan atau pesan standar. Jika undangan membutuhkan penanganan khusus, itu berarti logika aplikasi dan bukan tipe pesan.
Misalnya: sistem yang saya buat memiliki objek pesan dasar bersama yang diperluas menjadi SMS, Email, dan jenis pesan lainnya. Namun: ini tidak diperpanjang lebih lanjut - pesan undangan hanyalah teks yang telah ditentukan sebelumnya untuk dikirim melalui pesan jenis Email. Aplikasi Undangan tertentu akan berkaitan dengan validasi dan persyaratan lain untuk undangan. Lagi pula, yang ingin Anda lakukan adalah mengirim pesan X ke penerima Y yang seharusnya menjadi sistem tersendiri.
sumber
Masalah yang sama seperti Java. Coba gunakan antarmuka dengan fungsi abstrak untuk memecahkan masalah itu
sumber
PHP mendukung antarmuka. Ini bisa menjadi taruhan yang bagus, tergantung pada kasus penggunaan Anda.
sumber
Bagaimana dengan kelas Undangan tepat di bawah kelas Pesan?
jadi hirarki berjalan:
Pesan
--- Undangan
------ TextMessage
------ EmailMessage
Dan di kelas Invitation, tambahkan fungsionalitas yang ada di InvitationTextMessage dan InvitationEmailMessage.
Saya tahu bahwa Undangan sebenarnya bukan jenis Pesan, ini lebih merupakan fungsionalitas Pesan. Jadi saya tidak yakin apakah ini desain OO yang bagus atau tidak.
sumber