Apakah ada tujuan untuk mendeklarasikan init()
metode untuk suatu tipe?
Saya tidak bertanya apakah kita harus memilih init()
daripada konstruktor atau bagaimana menghindari menyatakaninit()
.
Aku bertanya apakah ada setiap alasan di balik mendeklarasikan init()
metode (melihat bagaimana umum itu) atau jika itu adalah kode bau dan harus dihindari.
The init()
idiom cukup umum, tapi saya belum melihat manfaat nyata.
Saya berbicara tentang tipe yang mendorong inisialisasi melalui metode:
class Demo {
public void init() {
//...
}
}
Kapan ini bisa digunakan dalam kode produksi?
Saya merasa itu mungkin bau kode karena itu menyarankan konstruktor tidak sepenuhnya menginisialisasi objek, menghasilkan objek yang dibuat sebagian. Objek seharusnya tidak ada jika statusnya tidak disetel.
Ini membuat saya percaya itu mungkin bagian dari semacam teknik yang digunakan untuk mempercepat produksi, dalam arti aplikasi perusahaan. Ini adalah satu-satunya alasan logis saya bisa memikirkan memiliki idiom seperti itu, saya hanya tidak yakin bagaimana itu akan bermanfaat jika demikian.
init()
kelas turunan, atau sebaliknya?) Jika demikian, ini adalah contoh membiarkan kelas dasar menjalankan "post-constructor "Yang hanya dapat dieksekusi setelah kelas yang paling diturunkan menyelesaikan konstruksi. Ini adalah contoh inisialisasi multi-fase.Jawaban:
Ya, ini bau kode. Bau kode bukan sesuatu yang selalu perlu dihapus. Itu adalah sesuatu yang membuat Anda melihat kedua.
Di sini Anda memiliki objek di dua negara yang berbeda secara mendasar: pra-init dan pasca-init. Negara-negara tersebut memiliki tanggung jawab yang berbeda, metode berbeda yang diizinkan untuk dipanggil, dan perilaku yang berbeda. Secara efektif dua kelas berbeda.
Jika Anda secara fisik membuat mereka dua kelas yang terpisah, Anda akan secara statis menghapus seluruh kelas bug potensial, dengan biaya mungkin membuat model Anda tidak cocok dengan "model dunia nyata" sedekat mungkin. Anda biasanya nama yang pertama
Config
atauSetup
atau sesuatu seperti itu.Jadi lain kali, coba refactoring idiom konstruk Anda menjadi model dua kelas dan lihat bagaimana hasilnya untuk Anda.
sumber
this
konstruktor adalah bau kode dan dapat mengakibatkan kode rawan kesalahan, dan menghindarinya dianjurkan terlepas dari domain apa proyek Anda berada).Tergantung.
Sebuah
init
metode adalah kode bau bila tidak perlu memiliki inisialisasi objek dipisahkan dari konstruktor. Terkadang ada kasus di mana masuk akal untuk memisahkan langkah-langkah ini.Pencarian Google cepat memberi saya contoh ini . Saya dapat dengan mudah membayangkan lebih banyak kasus di mana kode dieksekusi selama alokasi objek (konstruktor) mungkin lebih baik dipisahkan dari inisialisasi itu sendiri. Mungkin Anda memiliki sistem leveled, dan alokasi / konstruksi terjadi di level X, tetapi inisialisasi hanya di level Y, karena hanya Y yang dapat memberikan parameter yang diperlukan. Mungkin "init" mahal dan harus dijalankan hanya untuk subset dari objek yang dialokasikan, dan penentuan subset itu hanya dapat dilakukan di level Y. Atau Anda ingin menimpa metode "init" (virtual) dalam turunan kelas yang tidak dapat dilakukan dengan konstruktor. Mungkin level X memberi Anda objek yang dialokasikan dari pohon warisan, tetapi level Y tidak mengetahui derivasi beton, hanya tentang antarmuka umum (di mana
init
mungkin didefinisikan).Tentu saja, menurut pengalaman saya, kasus-kasus ini hanya sebagian kecil dari kasus standar di mana semua inisialisasi dapat dilakukan secara langsung dalam konstruktor, dan setiap kali Anda melihat
init
metode yang terpisah , mungkin ide yang baik untuk mempertanyakan perlunya.sumber
init
metode. Namun, setiap kali Anda melihat metode seperti itu, jangan ragu untuk mempertanyakan perlunya.init()
metode yang tepat, saya yakin saya akan mendapat manfaat dari belajar tentang tujuannya. Maafkan ketidaktahuan saya, saya hanya heran dengan betapa sulitnya waktu saya menemukan penggunaan untuk itu, mencegah saya dari menganggapnya sesuatu yang harus dihindariPengalaman saya dipecah menjadi dua kelompok:
Dalam pengalaman pribadi saya, saya telah melihat beberapa contoh (1) tetapi lebih banyak contoh (2). Akibatnya, saya biasanya menganggap init () adalah kode-bau, tetapi ini tidak selalu terjadi. Terkadang Anda tidak bisa menyiasatinya.
Saya telah menemukan menggunakan Pola Builder sering dapat membantu menghilangkan kebutuhan / keinginan untuk memiliki init ().
sumber
init()
metode menyelesaikannya? Theinit()
metode tersebut perlu parameter untuk menerima dependensi, atau Anda harus instantiate dependensi dalam satuinit()
metode, yang juga bisa dilakukan dengan konstruktor. Bisakah Anda memberi contoh?Skenario khas ketika metode Init berguna adalah ketika Anda memiliki file konfigurasi yang ingin Anda ubah dan agar perubahan diperhitungkan tanpa memulai ulang aplikasi. Ini, tentu saja, tidak berarti bahwa metode Init harus dipanggil secara terpisah dari konstruktor. Anda bisa memanggil metode Init dari konstruktor, dan kemudian memanggilnya nanti ketika / jika parameter konfigurasi berubah.
Singkatnya: seperti untuk sebagian besar dilema di luar sana, apakah ini bau kode atau tidak, tergantung pada situasi dan keadaan.
sumber
Config
?update
/reload
mungkin akan lebih deskriptif untuk perilaku semacam ini) untuk benar-benar mendaftar perubahan tersebut . Dalam hal itu, pemberitahuan itu akan menyebabkan nilai-nilai konfigurasi berubah di aplikasi Anda secara internal, yang saya yakin dapat diamati dengan membuat konfigurasi Anda dapat diamati, memberi tahu pengamat ketika konfigurasi diminta untuk mengubah salah satu dari nilai-nilai itu. Atau apakah saya salah memahami contoh Anda?Tergantung bagaimana Anda menggunakannya.
Saya menggunakan pola itu dalam bahasa yang dikumpulkan sampah seperti Java / C # ketika saya tidak ingin terus merealokasi objek di heap (seperti ketika saya membuat video game dan perlu menjaga kinerja tinggi, pengumpul sampah membunuh kinerja). Saya menggunakan konstruktor untuk membuat alokasi tumpukan lain yang dibutuhkan, dan
init
untuk membuat keadaan dasar yang berguna tepat sebelum setiap kali saya ingin menggunakannya kembali. Ini terkait dengan konsep kolam objek.Ini juga berguna jika Anda memiliki beberapa konstruktor yang berbagi subset umum dari instruksi inisialisasi, tetapi dalam kasus itu
init
akan bersifat pribadi. Dengan begitu saya dapat meminimalkan setiap konstruktor sebanyak mungkin, sehingga masing-masing hanya berisi instruksi unik dan satu panggilaninit
untuk melakukan sisanya.Secara umum, ini adalah bau kode.
sumber
reset()
metode akan lebih deskriptif untuk pernyataan pertama Anda? Adapun yang kedua (banyak konstruktor), memiliki banyak konstruktor adalah bau kode. Ini mengasumsikan objek memiliki beberapa tujuan / tanggung jawab, menunjukkan pelanggaran SRP. Objek harus memiliki satu tanggung jawab, dan konstruktor harus menentukan dependensi yang diperlukan untuk satu tanggung jawab itu. Jika Anda memiliki beberapa konstruktor karena nilai opsional, mereka harus menggunakan teleskop (yang juga merupakan bau kode, sebaiknya menggunakan pembangun).string
daftar konstruktor bahasa apa pun , berton-ton opsi. Bagi saya biasanya mungkin 3 konstruktor maks, tetapi bagian umum dari instruksi sebagai inisialisasi masuk akal ketika mereka berbagi kode apa pun tetapi berbeda dalam hal apa pun.String
, ini bisa diselesaikan dengan memisahkan pembuatan string. Pada akhirnya, aString
adalah aString
, dan konstruktornya hanya boleh menerima apa yang diperlukan agar dapat berfungsi sesuai kebutuhan. Sebagian besar konstruktor terbuka untuk tujuan konversi, yang merupakan penyalahgunaan konstruktor. Konstruktor tidak boleh melakukan logika, atau mereka berisiko gagal inisialisasi, meninggalkan Anda dengan objek yang tidak berguna.init()
metode bisa masuk akal ketika Anda memiliki objek yang membutuhkan sumber daya eksternal (seperti, misalnya, koneksi jaringan) yang secara bersamaan digunakan oleh objek lain. Anda mungkin tidak ingin / perlu menghabiskan sumber daya untuk seumur hidup objek. Dalam situasi seperti itu, Anda mungkin tidak ingin mengalokasikan sumber daya di konstruktor ketika alokasi sumber daya cenderung gagal.Khususnya dalam pemrograman tertanam, Anda ingin memiliki jejak memori deterministik, jadi itu praktik yang umum (baik?) Untuk memanggil konstruktor Anda lebih awal, bahkan mungkin statis, dan hanya menginisialisasi nanti ketika kondisi tertentu terpenuhi.
Selain kasus-kasus seperti itu saya pikir semuanya harus masuk ke konstruktor.
sumber
init
Metode yang sepenuhnya mengutuk terlalu membatasi, IMHO.Secara umum saya lebih suka konstruktor yang menerima semua argumen yang diperlukan untuk instance fungsional. Itu menjelaskan semua dependensi objek itu.
Di sisi lain, saya menggunakan kerangka kerja konfigurasi sederhana yang memerlukan konstruktor publik tanpa parameter, dan antarmuka untuk menyuntikkan dependensi dan nilai konfigurasi. Setelah itu selesai, kerangka konfigurasi memanggil
init
metode objek: sekarang Anda menerima semua hal yang saya miliki untuk Anda, lakukan langkah-langkah terakhir untuk bersiap-siap untuk bekerja. Tetapi perhatikan: ini adalah kerangka konfigurasi yang secara otomatis memanggil metode init, sehingga Anda tidak akan lupa untuk menyebutnya.sumber
Tidak ada bau kode jika metode init () - secara semantik tertanam dalam siklus keadaan-objek.
Jika Anda perlu memanggil init () untuk meletakkan objek ke dalam status yang konsisten, itu adalah bau kode.
Ada beberapa alasan teknis mengapa struktur seperti itu ada:
sumber
Nama init terkadang buram. Mari kita ambil mobil dan mesin. Untuk menyalakan mobil (hanya menghidupkan, mendengarkan radio), Anda ingin memastikan bahwa semua sistem siap digunakan.
Jadi Anda membangun mesin, pintu, roda dll. Layar Anda menunjukkan engine = off.
Tidak perlu mulai memantau mesin dll karena semuanya mahal. Kemudian ketika Anda memutar kunci untuk menyalakan Anda memanggil engine-> start. Itu mulai menjalankan semua proses mahal.
Sekarang Anda melihat engine = on. Dan proses pengapian dimulai.
Mobil tidak akan menyala tanpa mesin tersedia.
Anda dapat mengganti mesin dengan perhitungan kompleks Anda. Seperti sel Excel. Tidak semua sel harus aktif dengan semua penangan acara sepanjang waktu. Saat Anda fokus pada sel, Anda bisa memulainya. Meningkatkan kinerja seperti itu.
sumber