Apakah Anda pernah menggunakan variabel anggota yang dilindungi? Apa keuntungannya dan masalah apa yang bisa ditimbulkannya?
Apakah Anda pernah menggunakan variabel anggota yang dilindungi? Apa keuntungannya dan masalah apa yang bisa ditimbulkannya?
Jawaban:
Apakah Anda pernah menggunakan variabel anggota yang dilindungi?
Tergantung pada seberapa pilih-pilih Anda tentang keadaan persembunyian.
Jika seorang pengembang datang dan membuat subkelas dari kelas Anda, mereka mungkin mengacaukannya karena mereka tidak memahaminya sepenuhnya. Dengan anggota pribadi, selain antarmuka publik, mereka tidak dapat melihat detail spesifik implementasi tentang bagaimana sesuatu dilakukan yang memberi Anda fleksibilitas untuk mengubahnya nanti.
Perasaan umum saat ini adalah bahwa mereka menyebabkan kopling yang tidak semestinya antara kelas turunan dan basisnya.
Mereka tidak memiliki keunggulan tertentu atas metode / properti yang dilindungi (pada suatu waktu mereka mungkin memiliki sedikit keunggulan kinerja), dan mereka juga lebih banyak digunakan di era ketika warisan yang sangat dalam sedang populer, yang saat ini tidak ada.
no particular advantage over protected methods/properties
seharusnya no particular advantage over *private* methods/properties
?
super
konstruksi untuk memanggil konstruktor induk; itu kemudian akan mengurus inisialisasi variabel keadaan privat di kelas induk.
Umumnya, jika sesuatu tidak sengaja dipahami sebagai publik, saya membuatnya pribadi.
Jika muncul situasi di mana saya memerlukan akses ke variabel atau metode privat tersebut dari kelas turunan, saya mengubahnya dari privat menjadi dilindungi.
Ini hampir tidak pernah terjadi - saya sama sekali bukan penggemar warisan, karena ini bukan cara yang baik untuk mencontoh kebanyakan situasi. Bagaimanapun, lanjutkan, jangan khawatir.
Saya akan mengatakan ini baik-baik saja (dan mungkin cara terbaik untuk melakukannya) untuk sebagian besar pengembang.
Fakta sederhananya adalah , jika beberapa pengembang lain datang setahun kemudian dan memutuskan bahwa mereka memerlukan akses ke variabel anggota pribadi Anda, mereka hanya akan mengedit kode, mengubahnya menjadi dilindungi, dan melanjutkan bisnis mereka.
Satu-satunya pengecualian nyata untuk ini adalah jika Anda berada dalam bisnis pengiriman dll biner dalam bentuk kotak hitam ke pihak ketiga. Ini pada dasarnya terdiri dari Microsoft, vendor 'Custom DataGrid Control', dan mungkin beberapa aplikasi besar lainnya yang dikirimkan dengan perpustakaan yang dapat diperpanjang. Kecuali Anda termasuk dalam kategori itu, tidak ada gunanya menghabiskan waktu / tenaga untuk mengkhawatirkan hal semacam ini.
Masalah utama bagi saya adalah bahwa setelah Anda membuat variabel yang diproteksi, Anda tidak dapat mengizinkan metode apa pun di kelas Anda untuk mengandalkan nilainya berada dalam kisaran, karena subkelas selalu dapat menempatkannya di luar jangkauan.
Misalnya, jika saya memiliki kelas yang menentukan lebar dan tinggi objek yang dapat dirender, dan saya membuat variabel tersebut dilindungi, maka saya tidak dapat membuat asumsi atas (misalnya), rasio aspek.
Secara kritis, saya tidak pernah dapat membuat asumsi tersebut kapan pun sejak kode dirilis sebagai pustaka, karena meskipun saya memperbarui setter saya untuk mempertahankan rasio aspek, saya tidak menjamin bahwa variabel disetel melalui setter atau diakses melalui getter dalam kode yang ada.
Juga tidak ada subclass dari kelas saya yang memilih untuk membuat jaminan itu, karena mereka juga tidak dapat menerapkan nilai variabel, bahkan jika itu adalah inti dari subclass mereka .
Sebagai contoh:
Dengan membatasi variabel menjadi privat, saya kemudian dapat menerapkan perilaku yang saya inginkan melalui penyetel atau pengambil.
Secara umum, saya akan menyimpan variabel anggota terlindungi Anda pada kasus yang jarang terjadi di mana Anda memiliki kendali penuh atas kode yang menggunakannya juga. Jika Anda membuat API publik, saya akan mengatakan tidak pernah. Di bawah ini, kita akan menyebut variabel anggota sebagai "properti" dari objek.
Inilah yang tidak bisa dilakukan superclass Anda setelah membuat variabel anggota dilindungi daripada private-with-accessor:
dengan malas membuat nilai dengan cepat saat properti sedang dibaca. Jika Anda menambahkan metode getter yang dilindungi, Anda dapat dengan malas membuat nilai dan meneruskannya kembali.
tahu kapan properti itu diubah atau dihapus. Ini dapat menyebabkan bug ketika superclass membuat asumsi tentang status variabel itu. Membuat metode penyetel yang dilindungi untuk variabel mempertahankan kontrol itu.
Setel breakpoint atau tambahkan output debug saat variabel dibaca atau ditulis.
Ubah nama variabel anggota itu tanpa mencari semua kode yang mungkin menggunakannya.
Secara umum, saya pikir itu akan menjadi kasus yang jarang terjadi ketika saya merekomendasikan membuat variabel anggota yang dilindungi. Anda lebih baik menghabiskan beberapa menit untuk mengekspos properti melalui pengambil / penyetel daripada berjam-jam kemudian melacak bug di beberapa kode lain yang memodifikasi variabel yang dilindungi. Tidak hanya itu, Anda juga diasuransikan untuk tidak menambahkan fungsionalitas masa depan (seperti pemuatan lambat) tanpa merusak kode dependen. Lebih sulit melakukannya nanti daripada melakukannya sekarang.
Pada tingkat desain mungkin tepat untuk menggunakan properti yang dilindungi, tetapi untuk implementasi saya tidak melihat keuntungan dalam memetakan ini ke variabel anggota yang dilindungi daripada metode pengakses / mutator.
Variabel anggota yang dilindungi memiliki kerugian yang signifikan karena mereka secara efektif memungkinkan kode klien (sub-kelas) akses ke keadaan internal kelas kelas dasar. Ini mencegah kelas dasar dari secara efektif mempertahankan invariannya.
Untuk alasan yang sama, variabel anggota yang dilindungi juga membuat penulisan kode multi-utas yang aman jauh lebih sulit kecuali dijamin konstan atau terbatas pada utas tunggal.
Metode aksesor / mutator menawarkan stabilitas API dan fleksibilitas implementasi yang jauh lebih besar dalam pemeliharaan.
Selain itu, jika Anda seorang OO purist, objek berkolaborasi / berkomunikasi dengan mengirim pesan, bukan membaca / menyetel status.
Sebagai gantinya, mereka menawarkan sedikit keuntungan. Saya tidak perlu menghapusnya dari kode orang lain, tetapi saya tidak menggunakannya sendiri.
Sebagian besar waktu, berbahaya menggunakan protected karena Anda merusak enkapsulasi kelas Anda, yang bisa dipecah dengan baik oleh kelas turunan yang dirancang dengan buruk.
Tapi saya punya satu contoh bagus: Katakanlah Anda bisa beberapa jenis wadah umum. Ini memiliki implementasi internal, dan pengakses internal. Tapi Anda perlu menawarkan setidaknya 3 akses publik ke datanya: map, hash_map, vector-like. Kemudian Anda memiliki sesuatu seperti:
template <typename T, typename TContainer>
class Base
{
// etc.
protected
TContainer container ;
}
template <typename Key, typename T>
class DerivedMap : public Base<T, std::map<Key, T> > { /* etc. */ }
template <typename Key, typename T>
class DerivedHashMap : public Base<T, std::hash_map<Key, T> > { /* etc. */ }
template <typename T>
class DerivedVector : public Base<T, std::vector<T> > { /* etc. */ }
Saya menggunakan kode semacam ini kurang dari sebulan yang lalu (jadi kodenya dari memori). Setelah beberapa pemikiran, saya percaya bahwa sementara wadah Basis generik haruslah kelas abstrak, bahkan jika itu dapat hidup cukup baik, karena menggunakan Basis secara langsung akan sangat merepotkan, itu harus dilarang.
Ringkasan Jadi, Anda telah melindungi data yang digunakan oleh kelas turunan. Namun, kita harus memperhitungkan fakta bahwa kelas Base harus abstrak.
protected
tidak lebih dikemas dari public
. Saya bersedia terbukti salah. Yang harus Anda lakukan adalah menulis kelas dengan anggota yang dilindungi dan melarang saya untuk memodifikasinya. Jelas kelas harus non-final, karena inti dari penggunaan protected adalah untuk warisan. Entah ada sesuatu yang dikemas, atau tidak. Tidak ada negara bagian di antara keduanya.
Singkatnya, ya.
Variabel anggota yang dilindungi memungkinkan akses ke variabel dari sub-kelas apa pun serta kelas apa pun dalam paket yang sama. Ini bisa sangat berguna, terutama untuk data hanya-baca. Saya tidak percaya bahwa mereka pernah diperlukan, karena setiap penggunaan variabel anggota yang dilindungi dapat direplikasi menggunakan variabel anggota pribadi dan beberapa getter dan setter.
Untuk info mendetail tentang pengubah akses .net buka di sini
Tidak ada keuntungan atau kerugian nyata untuk variabel anggota yang dilindungi, ini adalah pertanyaan tentang apa yang Anda butuhkan dalam situasi khusus Anda. Secara umum, praktik yang dapat diterima untuk mendeklarasikan variabel anggota sebagai pribadi dan mengaktifkan akses luar melalui properti. Juga, beberapa alat (misalnya beberapa pembuat peta O / R) mengharapkan data objek diwakili oleh properti dan tidak mengenali variabel anggota publik atau dilindungi. Tetapi jika Anda tahu bahwa Anda ingin subclass Anda (dan HANYA subclass Anda) untuk mengakses variabel tertentu, tidak ada alasan untuk tidak mendeklarasikannya sebagai dilindungi.