Katakanlah dalam beberapa alasan semua objek dibuat dengan cara ini $ obj = CLASS :: getInstance (). Kemudian kami menyuntikkan dependensi menggunakan setter dan melakukan inisialisasi mulai menggunakan $ obj-> initInstance (); Apakah ada masalah atau situasi nyata, yang tidak dapat diselesaikan, jika kita tidak menggunakan konstruktor sama sekali?
Ps alasan untuk membuat objek dengan cara ini, adalah bahwa kita dapat mengganti kelas di dalam getInstance () sesuai dengan beberapa aturan.
Saya bekerja di PHP, jika itu penting
object-oriented-design
class-design
Axel Foley
sumber
sumber
Jawaban:
Saya akan mengatakan bahwa ini sangat menghambat ruang desain Anda.
Konstruktor adalah tempat yang bagus untuk menginisialisasi dan memvalidasi parameter yang dilewatkan. Jika Anda tidak bisa lagi menggunakannya untuk itu, maka inisialisasi, penanganan keadaan (atau jelas-jelas menyangkal konstruktor benda "rusak") menjadi jauh lebih sulit dan sebagian tidak mungkin.
Sebagai contoh, jika setiap
Foo
objek membutuhkanFrobnicator
maka mungkin memeriksa konstruktornya jikaFrobnicator
tidak nol. Jika Anda mengambil konstruktor, maka semakin sulit untuk memeriksa. Apakah Anda memeriksa setiap titik di mana itu akan digunakan? Dalam suatuinit()
metode (secara efektif mengeksternalisasi metode konstruktor)? Jangan pernah memeriksanya dan berharap yang terbaik?Meskipun Anda mungkin masih bisa mengimplementasikan semuanya (setelah semua, Anda masih belum selesai), beberapa hal akan jauh lebih sulit untuk dilakukan.
Secara pribadi saya akan menyarankan melihat Injeksi Ketergantungan / Inversi Kontrol . Teknik-teknik ini juga memungkinkan beralih kelas implementasi konkret, tetapi mereka tidak mencegah penulisan / penggunaan konstruktor.
sumber
HttpClient
lalu memeriksa apakah parameter itu bukan nol). Dan jika kendala itu tidak terpenuhi, maka bisa melempar pengecualian. Itu tidak benar-benar mungkin dengan pendekatan konstruk dan set nilai.init()
, yang sepenuhnya mungkin — meskipun ini hanya membebani lebih banyak beban pemeliharaan.2 keuntungan untuk konstruktor:
Konstruktor memungkinkan langkah konstruksi objek dilakukan secara atom.
Saya bisa menghindari konstruktor dan menggunakan setter untuk semuanya, tetapi bagaimana dengan properti wajib seperti yang disarankan Joachim Sauer? Dengan konstruktor, suatu objek memiliki logika konstruksinya sendiri untuk memastikan bahwa tidak ada instance kelas yang tidak valid .
Jika membuat instance dari
Foo
3 properti harus ditetapkan, konstruktor dapat mengambil referensi ke semua 3, memvalidasi mereka dan melemparkan pengecualian jika mereka tidak valid.Enkapsulasi
Dengan hanya mengandalkan setter, beban ada pada konsumen objek untuk membangunnya dengan benar. Mungkin ada kombinasi properti yang berbeda yang valid.
Misalnya, setiap
Foo
instance membutuhkan instanceBar
sebagai propertibar
atau instanceBarFinder
sebagai propertibarFinder
. Itu bisa menggunakan salah satunya. Anda dapat membuat konstruktor untuk setiap set parameter yang valid dan menerapkan konvensi seperti itu.Logika dan semantik untuk objek hidup di dalam objek itu sendiri. Enkapsulasi yang baik.
sumber
Ya, Anda bisa hidup tanpa konstruktor.
Tentu, Anda mungkin berakhir dengan banyak kode pelat ketel yang diduplikasi. Dan jika aplikasi Anda berskala apa pun, kemungkinan Anda akan menghabiskan banyak waktu untuk mencari sumber masalah ketika kode boilerplate tidak digunakan secara konsisten di seluruh aplikasi.
Tapi tidak, Anda tidak benar-benar 'membutuhkan' konstruktor Anda sendiri. Tentu saja, Anda juga tidak benar-benar 'membutuhkan' kelas dan objek.
Sekarang jika tujuan Anda adalah menggunakan semacam pola pabrik untuk pembuatan objek, itu tidak eksklusif untuk menggunakan konstruktor saat menginisialisasi objek Anda.
sumber
Keuntungan menggunakan konstruktor adalah mereka membuatnya lebih mudah untuk memastikan bahwa Anda tidak akan pernah memiliki objek yang tidak valid.
Konstruktor memberi Anda kesempatan untuk mengatur semua variabel anggota objek ke status yang valid. Ketika Anda kemudian memastikan bahwa tidak ada metode mutator dapat mengubah objek ke keadaan tidak valid, Anda tidak akan pernah memiliki objek yang tidak valid, yang akan menyelamatkan Anda dari banyak bug.
Tetapi ketika objek baru dibuat dalam keadaan tidak valid dan Anda harus memanggil beberapa setter untuk memasukkannya ke dalam status yang valid di mana ia dapat digunakan, Anda berisiko bahwa seorang konsumen kelas lupa untuk memanggil setter ini atau menyebutnya dengan salah dan Anda berakhir dengan objek yang tidak valid.
Solusinya bisa dengan membuat objek hanya melalui metode pabrik yang memeriksa setiap objek yang dibuatnya untuk validitas sebelum mengembalikannya ke pemanggil.
sumber
Saya pikir Anda membuat ini lebih sulit daripada yang seharusnya. Kami dapat menyuntikkan dependensi dengan baik melalui konstruktor - dan jika Anda memiliki banyak dependensi, cukup gunakan struktur seperti kamus sehingga Anda dapat menentukan yang mana yang ingin Anda gunakan:
Dan di dalam konstruktor, Anda dapat memastikan konsistensi seperti:
$args
kemudian dapat digunakan untuk mengatur anggota pribadi sesuai kebutuhan.Ketika dilakukan sepenuhnya dalam konstruktor seperti itu, tidak akan pernah ada keadaan peralihan di mana
$obj
ada tetapi tidak diinisialisasi, karena akan ada dalam sistem yang dijelaskan dalam pertanyaan. Lebih baik menghindari keadaan perantara seperti itu, karena Anda tidak dapat menjamin objek selalu akan digunakan dengan benar.sumber
Saya sebenarnya memikirkan hal-hal serupa.
Pertanyaan yang saya ajukan adalah "Apa yang dilakukan konstruktor, dan apakah mungkin melakukannya secara berbeda?" Saya mencapai kesimpulan itu:
Ini memastikan beberapa properti diinisialisasi. Dengan menerimanya sebagai parameter dan mengaturnya. Tapi ini bisa dengan mudah ditegakkan oleh kompiler. Dengan hanya memberi anotasi pada bidang atau properti sebagai "wajib", kompiler akan memeriksa selama pembuatan instance jika semuanya diatur dengan benar. Panggilan untuk membuat instance mungkin akan sama, tidak akan ada metode konstruktor.
Memastikan properti valid. Ini bisa dengan mudah dicapai dengan syarat tegas. Sekali lagi Anda hanya akan membubuhi keterangan properti dengan kondisi yang benar. Beberapa bahasa sudah melakukan ini.
Beberapa logika konstruksi yang lebih kompleks. Pola modern tidak merekomendasikan untuk melakukan itu dalam konstruktor, tetapi usulkan menggunakan metode atau kelas pabrik khusus. Jadi penggunaan konstruktor dalam hal ini minimal.
Jadi untuk menjawab pertanyaan Anda: Ya, saya percaya itu mungkin. Tetapi itu akan membutuhkan beberapa perubahan besar dalam desain bahasa.
Dan saya hanya memperhatikan jawaban saya cukup PL.
sumber
Ya, Anda dapat melakukan hampir semua hal tanpa menggunakan konstruktor tetapi ini jelas menyia-nyiakan manfaat dari bahasa Pemrograman Berorientasi Objek.
Dalam bahasa modern (saya akan berbicara di sini tentang C # program mana yang saya di) dapat Anda membatasi bagian kode yang dapat dijalankan hanya dalam konstruktor. Berkat itu Anda dapat menghindari kesalahan yang canggung. Salah satunya adalah pengubah baca saja :
Seperti yang direkomendasikan oleh Joachim Sauer sebelumnya, alih-alih menggunakan
Factory
derai desain, bacalah tentangDependency Injection
. Saya akan merekomendasikan membaca Dependency Injection dalam .NET oleh Mark Seemann .sumber
Instantiate objek dengan tipe tergantung pada persyaratan itu sangat mungkin. Itu bisa menjadi objek itu sendiri, menggunakan variabel global sistem untuk mengembalikan tipe tertentu.
Namun, memiliki kelas dalam kode yang dapat "Semua" adalah konsep tipe dinamis . Saya pribadi percaya bahwa pendekatan ini menciptakan ketidakkonsistenan dalam kode Anda, membuat kompleks pengujian *, dan "masa depan menjadi tidak pasti" sehubungan dengan aliran karya yang diusulkan.
* Saya merujuk pada fakta bahwa tes harus mempertimbangkan terlebih dahulu jenisnya, kedua hasil yang ingin Anda capai. Kemudian Anda membuat tes bersarang besar.
sumber
Untuk menyeimbangkan beberapa jawaban lain, dengan mengklaim:
dan
Pernyataan seperti itu terkadang menyiratkan asumsi bahwa:
Tetapi ini tidak sepenuhnya benar. Sebagian besar bahasa tidak memiliki aturan terhadap konstruktor yang meneruskan
this
(self
atau apa pun bahasa menyebutnya) ke kode eksternal. Konstruktor seperti itu sepenuhnya mematuhi aturan yang disebutkan di atas, namun berisiko mengekspos objek setengah jadi ke kode eksternal. Ini poin kecil tapi mudah diabaikan.sumber
Ini agak anekdotal, tetapi saya biasanya memesan konstruktor untuk keadaan penting agar objek menjadi lengkap dan dapat digunakan. Jika tidak ada penyetel-injeksi, begitu konstruktor dijalankan, objek saya harus dapat melakukan tugas-tugas yang diperlukan.
Apa pun yang dapat ditunda, saya tinggalkan konstruktor (menyiapkan nilai output, dll). Dengan pendekatan ini, saya merasa tidak menggunakan konstruktor untuk apa pun kecuali injeksi ketergantungan masuk akal.
Ini juga memiliki manfaat tambahan dari proses desain mental Anda untuk tidak melakukan apa-apa sebelum waktunya. Anda tidak akan menginisialisasi atau melakukan logika yang mungkin tidak pernah berakhir digunakan karena yang terbaik yang Anda lakukan adalah pengaturan dasar untuk pekerjaan di depan.
sumber