Apakah visibilitas private
bidang kelas / properti / atribut berguna? Dalam OOP, cepat atau lambat, Anda akan membuat subkelas dari sebuah kelas dan dalam hal itu, baik untuk memahami dan mampu memodifikasi implementasi sepenuhnya.
Salah satu hal pertama yang saya lakukan ketika saya mensubclass sebuah kelas adalah mengubah banyak private
metode menjadi protected
. Namun, menyembunyikan detail dari dunia luar itu penting – jadi kita perlu protected
dan bukan adil public
.
Pertanyaan saya adalah: Apakah Anda tahu tentang kasus penggunaan penting di mana private
alih-alih protected
merupakan alat yang baik, atau apakah dua opsi " protected
& public
" sudah cukup untuk bahasa OOP?
object-oriented
encapsulation
access-modifiers
Adam Libuša
sumber
sumber
Jawaban:
Karena seperti yang Anda katakan,
protected
masih memberi Anda kemampuan untuk "memodifikasi implementasi sepenuhnya". Itu tidak benar-benar melindungi apa pun di dalam kelas.Mengapa kita peduli tentang "melindungi dengan tulus" hal-hal di dalam kelas? Karena kalau tidak, tidak mungkin untuk mengubah detail implementasi tanpa melanggar kode klien . Dengan kata lain, orang yang menulis subclass juga "dunia luar" bagi orang yang menulis kelas dasar asli.
Dalam praktiknya,
protected
anggota pada dasarnya adalah "API publik untuk subkelas" kelas dan harus tetap stabil dan kompatibel dengan belakang seperti halnyapublic
anggota. Jika kami tidak memiliki kemampuan untuk membuatprivate
anggota sejati , maka tidak ada dalam implementasi yang akan aman untuk diubah, karena Anda tidak akan dapat mengesampingkan kemungkinan bahwa kode klien (tidak berbahaya) entah bagaimana berhasil bergantung pada saya t.Secara kebetulan, sementara "Dalam OOP, cepat atau lambat, Anda akan membuat subkelas kelas" secara teknis benar, argumen Anda tampaknya membuat asumsi yang jauh lebih kuat bahwa "cepat atau lambat, Anda akan membuat subkelas dari setiap kelas "yang hampir pasti bukan itu masalahnya.
sumber
private
benar-benar masuk akal bagi saya. Perspektif lib perlu lebih sering digunakan, jika tidak, siapa pun yang menyukai mentalitas "kendali absolut, tanggung jawab absolut" (seperti C) mungkin menandainya sebagai "melindungi saya dari diri saya sendiri". Perhatikan bahwa saya masih menggunakanprivate
sebelumnya, saya selalu merasa dokumentasi yang bagus dan konvensi penamaan ingin_foo
menunjukkan Anda mungkin tidak boleh mengacaukannya itu setara jika tidak lebih baik. Mampu secara deterministik mengatakan "tidak ada yang akan rusak" adalah fitur yang sah,private
hanya.Ini salah. Tidak setiap kelas dimaksudkan untuk subkelas dan beberapa bahasa OOP yang diketik secara statis bahkan memiliki fitur untuk mencegahnya, misalnya,
final
(Java dan C ++) atausealed
(C #).Tidak, tidak. Baik bagi kelas untuk dapat dengan jelas mendefinisikan antarmuka publiknya dan melestarikan invariannya meskipun itu diwarisi darinya.
Secara umum, kontrol akses adalah tentang kompartementalisasi. Anda ingin satu bagian dari kode dipahami tanpa harus memahami secara detail bagaimana ia berinteraksi dengan bagian kode yang lain. Akses pribadi memungkinkan itu. Jika semuanya setidaknya dilindungi, Anda harus memahami apa yang dilakukan setiap subclass untuk memahami cara kerja kelas dasar.
Atau dengan kata-kata Scott Meyers: bagian pribadi dari suatu kelas dipengaruhi oleh sejumlah kode: kode kelas itu sendiri.
Bagian publik berpotensi dipengaruhi oleh setiap bit kode yang ada, dan setiap bit kode belum ditulis, yang merupakan jumlah kode yang tak terbatas.
Bagian yang dilindungi berpotensi dipengaruhi oleh setiap subclass yang ada, dan setiap subclass yang belum ditulis, yang juga merupakan jumlah kode yang tak terbatas.
Kesimpulannya adalah bahwa dilindungi memberi Anda sedikit lebih banyak daripada publik, sedangkan pribadi memberi Anda peningkatan nyata. Keberadaan specifier akses yang dilindungi dipertanyakan, bukan pribadi.
sumber
virtual
, untuk alasan yang diuraikan dalam jawaban ini.protected
untuk metode, bukan untuk anggota data.sealed
bagian besar dari perpustakaan .net dan IIRC mengapa ia suka mengunci sisanya. Saat Anda mengizinkan pewaris pihak ketiga untuk mulai menyentuh nilai-nilai internal Anda perlu menambahkan sejumlah besar cek validasi / kewarasan untuk setiap metode karena Anda tidak bisa lagi mempercayai invarian desain tentang objek internal keadaan.Ya, bidang pribadi mutlak diperlukan. Baru minggu ini saya perlu menulis implementasi kamus khusus di mana saya mengontrol apa yang dimasukkan ke dalam kamus. Jika bidang kamus dibuat dilindungi atau publik, maka kontrol yang saya tulis dengan hati-hati bisa dengan mudah dielakkan.
Bidang pribadi biasanya tentang memberikan perlindungan bahwa data sesuai dengan yang diharapkan oleh pembuat kode asli. Jadikan semuanya terlindungi / publik dan Anda menunggangi pelatih dan kuda melalui prosedur dan validasi tersebut.
sumber
private
hanyalah cara untuk mengatakan "jangan sentuh ini", dan minta diberlakukan dalam kontrak kompiler. Dalam sistem seperti .NET, ini juga memiliki implikasi keamanan yang penting - Anda hanya dapat menyentuh privasi orang lain ketika Anda memiliki kepercayaan penuh (pada dasarnya setara dengan admin / akses root).Ketika mencoba memberi alasan secara formal tentang kebenaran program Berorientasi Objek , biasanya menggunakan pendekatan modular yang melibatkan invarian objek . Dalam pendekatan ini
Penalaran modular tentang suatu objek berlangsung sebagai berikut (setidaknya untuk perkiraan pertama)
Bayangkan kami memverifikasi dan
object A
menggunakan pendekatan di atas. Dan sekarang ingin memverifikasimethod g
dariobject B
yang panggilanmethod f
dariobject A
. Modular reasoning memungkinkan kita untuk berpikir tentangmethod g
tanpa harus mempertimbangkan kembali implementasimethod f
. Asalkan kita dapat menetapkan invarianobject A
dan prasyaratmethod f
di situs panggilan dimethod g,
kita dapat mengambil kondisi postingmethod f
sebagai ringkasan perilaku panggilan metode. Selain itu kita juga akan tahu bahwa setelah panggilan kembali invarianA
masih memegang.Modularitas penalaran inilah yang memungkinkan kita berpikir secara formal tentang program-program besar. Kita dapat memberi alasan tentang masing-masing metode secara individu dan kemudian menyusun hasil dari alasan ini pada gilirannya menjadi alasan tentang bagian-bagian yang lebih besar dari program.
Bidang pribadi sangat berguna dalam proses ini. Untuk mengetahui bahwa invarian objek terus bertahan di antara dua pemanggilan metode pada objek tersebut, kami biasanya bergantung pada fakta bahwa objek tersebut tidak dimodifikasi dalam periode intervensi.
Untuk penalaran modular untuk bekerja dalam konteks di mana objek tidak memiliki bidang pribadi maka kita harus memiliki beberapa cara untuk memastikan bahwa apa pun bidang yang kebetulan diatur ke objek lain, bahwa invarian selalu didirikan kembali (setelah bidang set). Sulit membayangkan objek invarian yang keduanya memegang tidak peduli apa nilai bidang objek, dan juga berguna dalam penalaran tentang kebenaran program. Kami mungkin harus membuat beberapa konvensi yang rumit di sekitar akses lapangan. Dan mungkin juga kehilangan sebagian (paling buruk bahkan semua) kemampuan kita untuk berpikir secara modular.
Bidang yang dilindungi
Bidang yang dilindungi mengembalikan sebagian kemampuan kami untuk bernalar secara modular. Tergantung pada bahasanya
protected
mungkin membatasi kemampuan untuk mengatur bidang ke semua subclass atau semua subclass dan kelas paket yang sama. Sering kali kita tidak memiliki akses ke semua subclass ketika kita beralasan tentang kebenaran suatu objek yang kita tulis. Misalnya, Anda mungkin menulis komponen atau pustaka yang nantinya akan digunakan dalam program yang lebih besar (atau beberapa program yang lebih besar) - beberapa di antaranya bahkan mungkin belum ditulis. Biasanya Anda tidak akan tahu jika dan dengan cara apa itu mungkin sub-kelas.Namun, biasanya ada kewajiban pada subclass untuk mempertahankan objek invarian dari kelas yang diperluas. Jadi, dalam bahasa di mana proteksi hanya berarti "sub-kelas", dan di mana kami didisiplinkan untuk memastikan bahwa sub-kelas selalu mempertahankan invarian dari superclass mereka, Anda dapat berargumen bahwa pilihan menggunakan yang dilindungi alih-alih swasta hanya kehilangan modularitas minimal .
Meskipun saya telah berbicara tentang penalaran formal, sering kali berpikir bahwa ketika programmer secara informal memberikan alasan tentang kebenaran kode mereka, mereka kadang-kadang juga bergantung pada jenis argumen yang serupa.
sumber
private
variabel dalam kelas lebih baik daripadaprotected
untuk alasan yang sama bahwabreak
pernyataan di dalamswitch
blok lebih baik daripadagoto label
pernyataan; yaitu bahwa pemrogram manusia cenderung melakukan kesalahan.protected
variabel meminjamkan diri mereka untuk penyalahgunaan yang tidak disengaja (kesalahan programmer), sepertigoto
pernyataan yang cocok untuk pembuatan kode spaghetti.Apakah mungkin untuk menulis kode bebas bug yang berfungsi menggunakan
protected
variabel kelas? Ya tentu saja! Sama seperti mungkin untuk menulis kode bebas bug menggunakan menggunakangoto
; tetapi sebagaimana klise berbunyi, "Hanya karena Anda bisa, tidak berarti Anda harus melakukannya!"Kelas, dan memang paradigma OO, ada untuk menjaga terhadap programmer manusia yang rentan kesalahan membuat kesalahan. Pertahanan melawan kesalahan manusia hanya sebagus tindakan defensif yang dibangun di dalam kelas. Membuat implementasi kelas Anda
protected
sama dengan meniup lubang besar di dinding benteng.Kelas dasar sama sekali tidak memiliki pengetahuan tentang kelas turunan. Sejauh menyangkut kelas dasar,
protected
sebenarnya tidak memberi Anda lebih banyak perlindungan daripadapublic
, karena tidak ada yang menghentikan kelas turunan dari membuatpublic
pengambil / penyetel yang berperilaku seperti pintu belakang.Jika kelas dasar mengizinkan akses tanpa hambatan ke detail implementasi internalnya, maka tidak mungkin bagi kelas itu sendiri untuk mempertahankan diri dari kesalahan. Kelas dasar sama sekali tidak memiliki pengetahuan tentang kelas turunannya, dan oleh karena itu tidak memiliki cara untuk menjaga terhadap kesalahan yang dibuat dalam kelas turunan tersebut.
Hal terbaik yang bisa dilakukan oleh kelas dasar adalah menyembunyikan sebanyak mungkin implementasinya
private
dan memberlakukan batasan yang cukup untuk menjaga agar tidak melanggar perubahan dari kelas turunan atau apa pun di luar kelas.Pada akhirnya, ada bahasa tingkat tinggi untuk meminimalkan kesalahan manusia. Praktik pemrograman yang baik (seperti prinsip SOLID ) juga ada untuk meminimalkan kesalahan manusia.
Pengembang perangkat lunak yang mengabaikan praktik pemrograman yang baik memiliki kemungkinan kegagalan yang jauh lebih tinggi, dan lebih mungkin menghasilkan solusi yang tidak dapat dipecahkan yang rusak. Mereka yang mengikuti praktik-praktik yang baik memiliki kemungkinan kegagalan yang jauh lebih rendah, dan lebih cenderung menghasilkan solusi yang dapat dipertahankan bekerja.
sumber
public
detail implementasi karena itu cocok untuk kode yang tidak dapat dipertahankan. Seorang programmer yang kompeten akan menghindarigoto
karena cocok untuk kode yang tidak dapat dipertahankan. Namun dunia nyata sedemikian rupa sehingga kadang-kadang Anda tersesat dalam kekacauan kode warisan yang mengerikan, dan tidak punya pilihan selain menggunakangoto
, dan untuk alasan yang sama Anda kadang-kadang tidak punya pilihan selain menggunakan detail implementasi publik / dilindungi.public
properti / antarmuka, tetapi tidak dengan kode yang hanya menggunakangoto
.goto
atau hanya karena Anda telah membaca artikel seperti itu? Saya mengerti mengapagoto
itu jahat karena saya telah menghabiskan 2 tahun bekerja dalam kode kuno yang menggunakannya; dan saya telah menghabiskan lebih lama lagi bekerja di kode di mana "kelas" memiliki detail implementasi mereka bocor di mana-mana denganpublic
danfriend
specifier digunakan sebagai peretasan cepat / mudah / kotor. Saya tidak menerima argumen bahwa "mengekspos detail implementasi secara publik" tidak dapat menyebabkan kekacauan spaghetti yang saling terkait pada tingkat keparahan yang samagoto
karena itu benar-benar bisa.Kelas yang tidak dapat diwarisi memiliki dua kontrak - satu dengan pemegang referensi objek, dan dengan kelas turunan. Anggota publik terikat oleh kontrak dengan pemegang referensi, dan anggota yang dilindungi terikat oleh kontrak dengan kelas turunan.
Membuat anggota
protected
menjadikannya kelas dasar yang lebih fleksibel, tetapi seringkali akan membatasi cara perubahan versi kelas di masa depan. Membuat anggotaprivate
memungkinkan penulis kelas lebih fleksibel untuk mengubah cara kerja kelas, tetapi membatasi jenis kelas yang dapat bermanfaat berasal darinya.Sebagai contoh,
List<T>
di .NET membuat backing store menjadi pribadi; jika dilindungi, tipe turunan dapat melakukan beberapa hal berguna yang jika tidak tidak mungkin, tetapi versi masa depanList<T>
akan selamanya harus menggunakan toko dukungan monolitik yang kikuk bahkan untuk daftar yang menyimpan jutaan item. Menjadikan toko dukungan pribadi akan memungkinkan versi masa depanList<T>
untuk menggunakan toko dukungan lebih efisien tanpa melanggar kelas turunan.sumber
Saya pikir ada asumsi kunci dalam argumen Anda bahwa ketika seseorang menulis kelas mereka tidak tahu siapa yang mungkin memperluas kelas itu di jalan dan untuk alasan apa . Dengan asumsi ini, argumen Anda akan masuk akal karena setiap variabel yang Anda buat bersifat pribadi maka berpotensi memotong jalan pengembangan. Namun, saya akan menolak anggapan itu.
Jika asumsi itu ditolak maka hanya ada dua kasus untuk dipertimbangkan.
Dalam hal ini, penulis tahu bahwa seseorang akan memperluas kelas dan mengapa dan oleh karena itu akan tahu persis apa yang harus dilindungi dan apa yang harus dijadikan rahasia. Mereka menggunakan perbedaan pribadi / terlindungi untuk mengkomunikasikan semacam antarmuka kepada pengguna yang membuat subkelas.
Kasing ini harus jarang (Anda bisa berargumen bahwa itu tidak sah), dan tidak disukai hanya memodifikasi kelas asli dalam basis kode asli. Ini juga bisa menjadi gejala desain yang buruk. Dalam kasus itu saya lebih suka orang yang melakukan peretasan hanya menggunakan peretasan lain seperti teman (C / C ++) dan
setAccessible(true)
(Jawa).Saya pikir aman untuk menolak asumsi itu.
Ini umumnya jatuh kembali ke ide komposisi di atas warisan . Warisan sering diajarkan sebagai cara yang ideal untuk mengurangi penggunaan kembali kode namun itu jarang menjadi pilihan pertama untuk penggunaan kembali kode. Saya tidak memiliki argumen knock-down sederhana dan itu bisa menjadi hal yang cukup sulit dan kontroversial untuk dipahami. Namun, dalam pengalaman saya dengan pemodelan domain saya telah menemukan bahwa saya jarang menggunakan warisan tanpa memiliki pemahaman yang sangat jelas tentang siapa yang akan mewarisi kelas saya dan mengapa.
sumber
Ketiga tingkat akses memiliki kasus penggunaannya, OOP akan menjadi tidak lengkap karena kekurangan salah satu dari mereka. Biasanya Anda melakukannya
Dan Anda menyimpang dari skema umum ini hanya jika ada alasan yang bagus ™ . Waspadalah terhadap "ini akan membuat hidup saya lebih mudah ketika saya dapat dengan bebas mengaksesnya dari luar" (dan di luar sini juga termasuk subclass). Ketika saya menerapkan hierarki kelas, saya sering mulai dengan kelas yang tidak memiliki anggota yang dilindungi, sampai saya datang untuk subklasifikasi / memperluas / mengkhususkan mereka, menjadi kelas dasar dari framework / toolkit dan kadang-kadang memindahkan bagian dari fungsi asli mereka satu tingkat ke atas.
sumber
Mungkin pertanyaan yang lebih menarik adalah mengapa diperlukan bidang jenis lain selain pribadi. Ketika sebuah subclass perlu berinteraksi dengan data superclass, melakukan hal itu secara langsung membuat kopling langsung antara keduanya, sedangkan menggunakan metode untuk menyediakan interaksi antara keduanya memungkinkan tingkat tipuan yang dapat memungkinkan untuk membuat perubahan pada superclass yang seharusnya sangat sulit.
Sejumlah bahasa (mis. Ruby dan Smalltalk) tidak menyediakan bidang publik sehingga pengembang tidak diperbolehkan untuk memungkinkan penggandengan langsung ke implementasi kelas mereka, tetapi mengapa tidak melangkah lebih jauh dan hanya memiliki bidang pribadi? Tidak akan ada kerugian umum (karena superclass selalu dapat menyediakan accessors yang dilindungi untuk subclass), tetapi akan memastikan bahwa kelas selalu memiliki setidaknya tingkat isolasi kecil dari subclass mereka. Mengapa ini bukan desain yang lebih umum?
sumber
Banyak jawaban bagus di sini, tapi saya akan tetap menggunakan dua sen saya. :-)
Pribadi baik untuk alasan yang sama bahwa data global buruk.
Jika suatu kelas mendeklarasikan data pribadi, maka Anda benar-benar tahu bahwa satu-satunya kode yang mengacaukan data ini adalah kode di dalam kelas. Ketika ada bug, Anda tidak perlu mencari di seluruh kreasi untuk menemukan setiap tempat yang dapat mengubah data ini. Anda tahu itu di kelas. Saat Anda membuat perubahan pada kode, dan Anda mengubah sesuatu tentang bagaimana bidang ini digunakan, Anda tidak harus melacak semua tempat potensial yang mungkin menggunakan bidang ini dan mempelajari apakah perubahan yang Anda rencanakan akan menghancurkannya. Anda tahu satu-satunya tempat di dalam kelas.
Saya sudah berkali-kali harus membuat perubahan pada kelas yang ada di perpustakaan dan digunakan oleh banyak aplikasi, dan saya harus menginjak dengan sangat hati-hati untuk memastikan saya tidak merusak beberapa aplikasi yang tidak saya ketahui. Semakin banyak data publik dan yang dilindungi, semakin besar potensi masalah.
sumber
Saya pikir perlu menyebutkan beberapa pendapat yang berbeda pendapat.
Secara teori, ada baiknya mengontrol tingkat akses untuk semua alasan yang disebutkan dalam jawaban lain.
Dalam praktiknya, terlalu sering ketika meninjau kode, saya melihat orang-orang (yang suka menggunakan pribadi), mengubah tingkat akses dari pribadi -> dilindungi dan tidak terlalu sering dari dilindungi -> publik. Hampir selalu, mengubah properti kelas melibatkan memodifikasi setter / getter. Ini telah menyita banyak waktu saya (review kode) dan mereka (mengubah kode).
Ini juga mengganggu saya bahwa itu berarti kelas mereka tidak Ditutup untuk modifikasi.
Itu dengan kode internal di mana Anda selalu dapat mengubahnya jika perlu juga. Situasi lebih buruk dengan kode pihak ke-3 ketika tidak mudah untuk mengubah kode.
Jadi, berapa banyak programmer yang menganggapnya merepotkan? Nah, berapa banyak yang menggunakan bahasa pemrograman yang tidak memiliki privat? Tentu saja, orang tidak hanya menggunakan bahasa-bahasa itu karena mereka tidak memiliki specifier swasta, tetapi membantu untuk menyederhanakan bahasa dan kesederhanaan itu penting.
Imo itu sangat mirip dengan pengetikan dinamis / statis. Secara teori, pengetikan statis sangat baik. Dalam prakteknya, itu hanya mencegah seperti 2% dari kesalahan tersebut tidak masuk akal Efektivitas Dinamis Mengetik ... . Menggunakan pribadi mungkin mencegah kesalahan kurang dari itu.
Saya pikir prinsip-prinsip SOLID baik, saya berharap orang lebih peduli tentang mereka daripada mereka peduli menciptakan kelas dengan publik, dilindungi dan pribadi.
sumber
Saya juga ingin menambahkan contoh praktis lain mengapa
protected
tidak cukup. Di universitas saya tahun-tahun pertama melakukan proyek di mana mereka harus mengembangkan versi desktop dari permainan papan (yang kemudian dikembangkan untuk AI dan terhubung ke pemain lain melalui jaringan). Beberapa kode parsial disediakan bagi mereka untuk memulainya termasuk kerangka pengujian. Beberapa properti dari kelas game utama dieksposprotected
sehingga kelas tes yang memperluas kelas ini memiliki akses ke mereka. Tetapi bidang ini bukan informasi sensitif.Sebagai TA untuk unit saya sering melihat siswa hanya membuat semua kode tambahan mereka
protected
ataupublic
(mungkin karena mereka melihat yang lainprotected
danpublic
barang-barang dan menganggap mereka harus mengikuti). Saya bertanya kepada mereka mengapa tingkat perlindungan mereka tidak pantas, dan banyak yang tidak tahu mengapa. Jawabannya adalah bahwa informasi sensitif yang mereka paparkan ke subclass berarti bahwa pemain lain dapat menipu dengan hanya memperluas kelas itu dan mengakses informasi yang sangat sensitif untuk permainan (pada dasarnya lokasi tersembunyi lawan, saya kira mirip dengan bagaimana jadinya jika Anda bisa melihat potongan lawan Anda di papan kapal perang dengan memperpanjang beberapa kelas). Itu membuat kode mereka sangat berbahaya dalam konteks permainan.Selain itu, ada banyak alasan lain untuk menjaga sesuatu tetap pribadi bahkan untuk subkelas Anda. Mungkin menyembunyikan detail implementasi yang dapat mengacaukan kerja kelas dengan benar jika diubah oleh seseorang yang tidak perlu tahu apa yang mereka lakukan (kebanyakan memikirkan orang lain yang menggunakan kode Anda di sini).
sumber
Metode / variabel pribadi umumnya akan disembunyikan dari subkelas. Itu bisa menjadi hal yang baik.
Metode pribadi dapat membuat asumsi tentang parameter dan membiarkan kewarasan memeriksa ke pemanggil.
Metode yang dilindungi harus memeriksa input kewarasan.
sumber
"Pribadi" berarti: Tidak dimaksudkan untuk diubah atau diakses oleh siapa pun kecuali kelas itu sendiri. Tidak dimaksudkan untuk diubah atau diakses oleh subclass. Subkelas? Subkelas apa? Anda tidak seharusnya mensubklasifikasikan ini!
"protected" berarti: Hanya dimaksudkan untuk diubah atau diakses oleh kelas atau subclass. Mungkin deduksi bahwa Anda seharusnya subclass, kalau tidak mengapa "dilindungi" dan bukan "pribadi"?
Ada perbedaan yang jelas di sini. Jika saya membuat sesuatu pribadi, Anda harus menjaga jari-jari Anda yang kotor. Bahkan jika Anda adalah subkelas.
sumber
Beberapa penalaran tentang
private
vsprotected
metode :private
metode mencegah penggunaan kembali kode. Subkelas tidak dapat menggunakan kode dalam metode pribadi dan mungkin harus mengimplementasikannya lagi - atau menerapkan kembali metode yang awalnya bergantung pada metode pribadi & c.Di sisi lain, metode apa pun yang tidak
private
dapat dilihat sebagai API yang disediakan oleh kelas untuk "dunia luar", dalam arti bahwa subkelas pihak ketiga juga dianggap "dunia luar", seperti yang disarankan orang lain dalam jawabannya. sudah.Itu adalah hal yang buruk? - Kurasa tidak.
Tentu saja, API publik (pseudo-) mengunci programmer asli dan menghalangi refactoring dari antarmuka tersebut. Tetapi jika dilihat sebaliknya, mengapa seorang programmer tidak perlu mendesain sendiri "detail implementasi" dengan cara yang bersih dan stabil seperti API publiknya? Haruskah dia menggunakan
private
sehingga dia bisa ceroboh tentang penataan kode "pribadi" nya? Berpikir mungkin dia bisa membersihkannya nanti, karena tidak ada yang akan memperhatikan? - Tidak.Programmer harus memasukkan sedikit pemikiran ke dalam kode "privat" -nya juga, untuk menyusunnya sedemikian rupa sehingga memungkinkan atau bahkan mempromosikan penggunaan ulang sebanyak mungkin di tempat pertama. Maka bagian-bagian non-pribadi mungkin tidak menjadi beban di masa depan seperti beberapa ketakutan.
Banyak (framework) kode saya melihat mengadopsi penggunaan konsisten dari
private
:protected
, metode non-final yang hampir tidak melakukan apa-apa lebih dari mendelegasikan kepada metode pribadi umumnya ditemukan.protected
, metode non-final yang kontraknya hanya dapat dipenuhi melalui akses langsung ke bidang pribadi juga.Metode-metode ini tidak dapat secara logis diganti / ditingkatkan, meskipun secara teknis tidak ada yang membuat (compiler-) jelas.
Ingin dapat diperpanjang dan diwariskan? Jangan membuat metode Anda
private
.Tidak ingin perilaku kelas Anda diubah? Buat metode Anda
final
.Benarkah metode Anda tidak bisa disebut di luar konteks tertentu yang terdefinisi dengan baik? Jadikan metode Anda
private
dan / atau pikirkan tentang bagaimana Anda dapat membuat konteks yang ditentukan dengan baik tersedia untuk digunakan kembali melaluiprotected
metode pembungkus lain .Itu sebabnya saya menganjurkan untuk menggunakan
private
hemat. Dan tidak membingungkanprivate
denganfinal
. - Jika implementasi metode sangat penting untuk kontrak umum kelas dan karenanya tidak boleh diganti / diganti, buatlahfinal
!Untuk bidang,
private
tidak terlalu buruk. Selama bidang tersebut dapat "digunakan" secara wajar melalui metode yang sesuai (itu tidakgetXX()
atausetXX()
!).sumber
private
vsprotected
, memberikan saran yang salah ("gunakanprivate
hemat"?) Dan bertentangan dengan konsensus umum tentang desain OO. Menggunakanprivate
tidak ada hubungannya dengan menyembunyikan kode ceroboh.private
membantu menjaga API tetap bersih.Pribadi : ketika Anda memiliki sesuatu yang tidak akan pernah berguna untuk memanggil atau mengganti subclass.
Dilindungi : ketika Anda memiliki sesuatu yang memiliki implementasi / konstanta khusus subkelas.
Sebuah contoh:
sumber
Sulit bagi saya untuk memahami masalah ini, jadi saya ingin berbagi pengalaman saya:
$classInstance->field
. Dan triknya adalah "ini dia". Anak-anak kelas Anda akan memiliki akses penuh ke sana, karena itu adalah bagian internal yang sah.PEMBARUAN: contoh praktis dari tugas nyata yang telah saya pecahkan. Ini dia: Anda punya token, seperti USB atau LPT (itu kasus saya), dan Anda punya middleware. Token meminta Anda kode pin, terbuka jika itu benar dan Anda dapat mengirim bagian terenkripsi dan sejumlah kunci untuk menguraikan. Kunci disimpan dalam token, Anda tidak dapat membacanya, hanya menggunakannya. Dan ada kunci sementara untuk sesi, ditandatangani oleh kunci dalam token, tetapi disimpan dalam middleware itu sendiri. Kunci temp tidak seharusnya bocor ke mana saja di luar, hanya ada pada level pengemudi. Dan saya menggunakan bidang pribadi untuk menyimpan kunci sementara ini dan beberapa data yang terkait dengan perangkat keras. Jadi tidak ada turunan yang dapat menggunakan tidak hanya antarmuka publik, tetapi juga beberapa yang dilindungisubrutin "berguna" yang saya buat untuk tugas, tetapi tidak dapat membuka kotak kuat dengan kunci dan interaksi HW. Masuk akal?
sumber