Mengapa kita harus menjadikan konstruktor pribadi di kelas? Karena kita selalu membutuhkan konstruktor untuk menjadi publik.
134
Beberapa alasan di mana Anda mungkin memerlukan konstruktor pribadi:
final
level kelas. Menempatkan konstruktor pribadi tidak berguna karena alasan ini.final
. Inilah yang Sun lakukan untuk kelas String, dan potongan yang wajar dari API yang seharusnya tidak diperpanjang.Dengan menyediakan konstruktor pribadi Anda mencegah instance kelas dari diciptakan di tempat lain selain kelas ini. Ada beberapa kasus penggunaan untuk menyediakan konstruktor tersebut.
A. Instance kelas Anda dibuat dalam suatu
static
metode. Thestatic
Metode ini kemudian dinyatakan sebagaipublic
.B. Kelas Anda adalah singleton . Ini berarti, tidak lebih dari satu instance kelas Anda ada di program.
C. (Hanya berlaku untuk standar C ++ 0x yang akan datang) Anda memiliki beberapa konstruktor. Beberapa dari mereka dinyatakan
public
, yang lainprivate
. Untuk mengurangi ukuran kode, konstruktor publik 'memanggil' konstruktor pribadi yang pada gilirannya melakukan semua pekerjaan.public
Konstruktor Anda disebut konstruktor pendelegasian :D. Anda ingin membatasi penyalinan objek (misalnya, karena menggunakan sumber daya bersama):
E. Kelas Anda adalah kelas utilitas . Itu artinya, hanya berisi
static
anggota. Dalam hal ini, tidak ada instance objek yang harus dibuat dalam program.sumber
Untuk meninggalkan "pintu belakang" yang memungkinkan kelas teman lain / fungsi untuk membangun objek dengan cara yang dilarang untuk pengguna. Contoh yang terlintas dalam pikiran adalah wadah yang membangun iterator (C ++):
sumber
friend
mana itu tidak dijamin - dan ada banyak kasus di mana itu adalah ide yang buruk. Sayangnya, pesan tersebut telah diterima dengan baik, dan banyak pengembang tidak pernah mempelajari bahasa dengan cukup baik untuk memahami bahwa penggunaan sesekalifriend
tidak hanya dapat diterima, tetapi lebih disukai . Contoh Anda adalah kasus seperti itu. Kopling kuat yang disengaja bukanlah kejahatan, ini adalah keputusan desain.Semua orang terjebak pada masalah Singleton, wow.
Hal-hal lain:
sumber
Ini bisa sangat berguna untuk konstruktor yang berisi kode umum; konstruktor pribadi dapat dipanggil oleh konstruktor lain, menggunakan 'this (...);' notasi. Dengan membuat kode inisialisasi umum dalam konstruktor pribadi (atau yang dilindungi), Anda juga membuat jelas secara eksplisit bahwa kode itu hanya dipanggil selama konstruksi, yang tidak demikian jika hanya berupa metode:
sumber
Ada beberapa contoh di mana Anda mungkin tidak ingin menggunakan konstruktor publik; misalnya jika Anda ingin kelas singleton.
Jika Anda menulis sebuah majelis yang digunakan oleh pihak ke-3 mungkin ada sejumlah kelas internal yang Anda hanya ingin dibuat oleh majelis Anda dan tidak akan dipakai oleh pengguna majelis Anda.
sumber
Ini memastikan bahwa Anda (kelas dengan konstruktor pribadi) mengontrol bagaimana konstruktor dipanggil.
Contoh: Metode pabrik statis di kelas dapat mengembalikan objek ketika metode pabrik memilih untuk mengalokasikannya (seperti pabrik tunggal misalnya).
sumber
Kita juga dapat memiliki konstruktor pribadi, untuk memulai pembuatan objek hanya dengan kelas tertentu (Untuk alasan keamanan).
Salah satu cara untuk melakukannya adalah melalui kelas teman.
Contoh C ++:
Catatan: Catatan: Hanya ClientClass (karena itu adalah teman SecureClass) yang dapat memanggil Constructor SecureClass.
sumber
Berikut adalah beberapa penggunaan konstruktor pribadi:
sumber
ketika Anda tidak ingin pengguna membuat instance kelas ini atau membuat kelas yang mewarisi kelas ini, seperti
java.lang.math
, semua fungsi dalam paket inistatic
, semua fungsi dapat dipanggil tanpa membuat turunanmath
, sehingga konstruktor diumumkan sebagai statis .sumber
Jika bersifat pribadi, maka Anda tidak dapat menyebutnya ==> Anda tidak dapat membuat instance kelas. Berguna dalam beberapa kasus, seperti singleton.
Ada diskusi dan beberapa contoh lagi di sini .
sumber
Saya melihat pertanyaan dari Anda menangani masalah yang sama.
Sederhananya jika Anda tidak ingin orang lain membuat instance, maka pertahankan konstuktor dalam ruang lingkup terbatas. Aplikasi praktis (Contoh) adalah pola tunggal.
sumber
Anda seharusnya tidak menjadikan konstruktor sebagai pribadi. Titik. Buat itu terlindungi, sehingga Anda dapat memperpanjang kelas jika perlu.
Sunting: Saya mendukung itu, tidak peduli berapa banyak downvotes yang Anda lemparkan pada ini. Anda memotong potensi untuk pengembangan kode di masa mendatang. Jika pengguna atau pemrogram lain benar-benar bertekad untuk memperluas kelas, maka mereka hanya akan mengubah konstruktor menjadi dilindungi dalam sumber atau bytecode. Anda tidak akan mencapai apa pun selain untuk membuat hidup mereka sedikit lebih sulit. Sertakan peringatan dalam komentar konstruktor Anda, dan biarkan di situ.
Jika ini adalah kelas utilitas, solusi yang lebih sederhana, lebih benar, dan lebih elegan adalah menandai seluruh kelas "final statis" untuk mencegah ekstensi. Tidak ada gunanya hanya menandai konstruktor pribadi; pengguna yang benar-benar bertekad selalu dapat menggunakan refleksi untuk mendapatkan konstruktor.
Penggunaan yang valid:
protected
konstruktor yang baik adalah dengan memaksa penggunaan metode pabrik statis, yang memungkinkan Anda untuk membatasi instantiasi atau mengumpulkan & menggunakan kembali sumber daya yang mahal (koneksi DB, sumber daya asli).sumber
Konstruktor bersifat pribadi untuk beberapa tujuan seperti ketika Anda perlu mengimplementasikan singleton atau membatasi jumlah objek kelas. Misalnya dalam implementasi singleton kita harus menjadikan konstruktor sebagai pribadi
Sekali lagi jika Anda ingin membatasi pembuatan objek hingga 10 maka gunakan yang berikut ini
Terima kasih
sumber
Anda dapat memiliki lebih dari satu konstruktor. C ++ menyediakan konstruktor default dan konstruktor salin default jika Anda tidak menyediakan secara eksplisit. Misalkan Anda memiliki kelas yang hanya dapat dibangun menggunakan beberapa konstruktor berparameter. Mungkin itu menginisialisasi variabel. Jika pengguna kemudian menggunakan kelas ini tanpa konstruktor itu, mereka dapat menyebabkan masalah tanpa akhir. Aturan umum yang baik: Jika implementasi default tidak valid, jadikan konstruktor default dan salin menjadi pribadi dan jangan berikan implementasi:
Gunakan kompiler untuk mencegah pengguna menggunakan objek dengan konstruktor default yang tidak valid.
sumber
Mengutip dari Java Efektif , Anda dapat memiliki kelas dengan konstruktor pribadi untuk memiliki kelas utilitas yang mendefinisikan konstanta (sebagai bidang final statis).
( EDIT: Sesuai komentar, ini adalah sesuatu yang mungkin hanya dapat diterapkan dengan Java, saya tidak mengetahui apakah konstruk ini berlaku / diperlukan dalam bahasa OO lainnya (katakanlah C ++))
Contohnya seperti di bawah ini:
EDIT_1 : Sekali lagi, penjelasan di bawah ini berlaku di Jawa: (dan merujuk dari buku, Java Efektif )
Instansiasi kelas utilitas seperti yang di bawah ini, meskipun tidak berbahaya, tidak melayani tujuan apa pun karena mereka tidak dirancang untuk dipakai.
Misalnya, katakanlah tidak ada Konstruktor pribadi untuk Konstanta kelas. Potongan kode seperti di bawah ini valid tetapi tidak lebih baik menyampaikan maksud pengguna kelas Konstanta
berbeda dengan kode like
Juga saya pikir konstruktor pribadi menyampaikan maksud perancang kelas Constants (katakanlah) lebih baik.
Java menyediakan konstruktor publik tanpa parameter default jika tidak ada konstruktor yang disediakan, dan jika niat Anda adalah mencegah instantiasi maka konstruktor pribadi diperlukan.
Seseorang tidak dapat menandai kelas statis tingkat atas dan bahkan kelas akhir dapat dipakai.
sumber
Kelas utilitas dapat memiliki konstruktor pribadi. Pengguna kelas tidak boleh membuat instance kelas-kelas ini:
sumber
Anda mungkin ingin mencegah kelas untuk dipakai secara bebas. Lihat pola desain singleton sebagai contoh. Untuk menjamin keunikan, Anda tidak dapat membiarkan siapa pun membuat instance dari itu :-)
sumber
Salah satu penggunaan penting adalah di kelas SingleTon
Ini juga cocok, Jika kelas Anda hanya memiliki metode statis. yaitu tidak ada yang perlu instantiate kelas Anda
sumber
Ini benar-benar satu alasan yang jelas: Anda ingin membangun objek, tetapi tidak praktis untuk melakukannya (dalam hal antarmuka) dalam konstruktor.
The
Factory
contoh adalah cukup jelas, biarkan aku menunjukkanNamed Constructor
idiom.Katakanlah saya memiliki kelas
Complex
yang dapat mewakili bilangan kompleks.Pertanyaannya adalah: apakah konstruktor mengharapkan bagian yang nyata dan imajiner, atau apakah ia mengharapkan norma dan sudut (koordinat kutub)?
Saya dapat mengubah antarmuka untuk membuatnya lebih mudah:
Ini disebut
Named Constructor
idiom: kelas hanya dapat dibangun dari awal dengan secara eksplisit menyatakan konstruktor mana yang ingin kita gunakan.Ini adalah kasus khusus dari banyak metode konstruksi. Pola Desain memberikan baik jumlah cara untuk membangun objek:
Builder
,Factory
,Abstract Factory
, ... dan konstruktor pribadi akan memastikan bahwa pengguna benar dibatasi.sumber
Selain kegunaan yang lebih dikenal ...
Untuk menerapkan pola Object Method , yang saya ringkas sebagai:
Jika Anda ingin menerapkan fungsi menggunakan objek, dan objek tidak berguna di luar melakukan perhitungan satu kali (dengan pemanggilan metode), maka Anda memiliki Objek Throwaway . Anda dapat merangkum pembuatan objek dan pemanggilan metode dalam metode statis, mencegah anti-pola umum ini:
... menggantinya dengan panggilan fungsi (namespaced):
Penelepon tidak perlu tahu atau peduli bahwa Anda menggunakan objek secara internal, menghasilkan antarmuka yang lebih bersih, dan mencegah sampah dari objek berkeliaran atau penggunaan objek yang salah.
Misalnya, jika Anda ingin memecah perhitungan di seluruh metode
foo
,,bar
danzork
, misalnya untuk berbagi keadaan tanpa harus melewati banyak nilai masuk dan keluar dari fungsi, Anda bisa menerapkannya sebagai berikut:Metode ini Pola objek diberikan dalam Smalltalk Best Practice Patterns , Kent Beck, halaman 34-37, di mana ini adalah langkah terakhir dari pola refactoring, yang berakhir:
Ini berbeda secara signifikan dari contoh-contoh lain di sini: kelasnya instantiable (tidak seperti kelas utilitas), tetapi instansnya pribadi (tidak seperti metode pabrik, termasuk lajang dll.), Dan dapat hidup di stack, karena mereka tidak pernah keluar.
Pola ini sangat berguna dalam OOP dasar, di mana objek digunakan untuk menyederhanakan implementasi tingkat rendah, tetapi tidak perlu diekspos secara eksternal, dan kontras dengan OOP top-down yang sering disajikan dan dimulai dengan antarmuka tingkat tinggi.
sumber
Terkadang berguna jika Anda ingin mengontrol bagaimana dan kapan (dan berapa banyak) instance dari objek dibuat.
Antara lain, digunakan dalam pola:
sumber
Penggunaan konstruktor pribadi juga bisa untuk meningkatkan keterbacaan / pemeliharaan dalam menghadapi desain berbasis domain. Dari "Microsoft .NET - Aplikasi Architecing untuk Perusahaan, Edisi ke-2":
Mengutip, "Ada dua masalah di sini. Pertama, ketika melihat kode, orang hampir tidak bisa menebak apa yang terjadi. Contoh dari OrderRequest sedang dibuat, tetapi mengapa dan menggunakan data yang mana? Apa 1234? Ini mengarah ke masalah kedua: Anda melanggar bahasa di mana-mana dari konteks yang dibatasi. Bahasa ini mungkin mengatakan sesuatu seperti ini: pelanggan dapat mengeluarkan permintaan pesanan dan diizinkan untuk menentukan ID pembelian. Jika demikian, inilah cara yang lebih baik untuk mendapatkan contoh OrderRequest baru : "
dimana
Saya tidak menganjurkan ini untuk setiap kelas tunggal, tetapi untuk skenario DDD di atas saya pikir itu masuk akal untuk mencegah penciptaan langsung objek baru.
sumber