Saya memiliki kelas dengan variabel yang bersifat pribadi dan kelas memiliki pengambil dan penyetel untuk variabel itu. Mengapa tidak menjadikan variabel itu publik?
Satu-satunya kasus saya pikir Anda harus menggunakan getter dan setter adalah jika Anda perlu melakukan beberapa operasi selain set atau get. Contoh:
void my_class::set_variable(int x){
/* Some operation like updating a log */
this->variable = x;
}
this->variable = x + 5
, atau memanggilUpdateStatistics
fungsi dalam setter, dan dalam kasus-kasus ituclassinstancea->variable = 5
akan menyebabkan masalah.set_inch
,set_centimeter
,get_inch
,get_centimeter
, dengan beberapa tindakan seram.Jawaban:
Pernahkah Anda mendengar tentang properti?
Properti adalah bidang yang memiliki aksesor "bawaan" (getter dan setter). Java, misalnya, tidak memiliki properti, tetapi disarankan untuk menulis getter dan setter ke bidang pribadi. C # memiliki properti.
Jadi, mengapa kita membutuhkan getter dan setter? Pada dasarnya kita membutuhkannya untuk melindungi / melindungi lapangan. Misalnya, Anda tidak mengakses bidang dalam referensi memori, Anda sedang mengakses metode yang kemudian akan mengubah bidang (referensi). Metode itu mampu melakukan beberapa operasi yang pengguna tidak mau tahu ( perilaku enkapsulasi ), seperti dalam contoh Anda. Bayangkan, misalnya, bahwa selusin kelas menggunakan bidang publik Anda dan Anda perlu mengubah cara itu digunakan ... Anda harus melihat masing-masing kelas untuk mengubah cara mereka menggunakan bidang ... Tidak jadi "OOlysh".
Tapi, misalnya, Jika Anda memiliki bidang boolean yang disebut mati. Anda harus berpikir dua kali sebelum mendeklarasikan setDead dan isDead. Anda harus menulis pengakses yang dapat dibaca manusia , misalnya, kill () alih-alih setDead.
Namun, ada banyak kerangka kerja yang menganggap bahwa Anda mengikuti konvensi penamaan JavaBean (berbicara tentang Java di sini), oleh karena itu, dalam kasus tersebut, Anda harus mendeklarasikan semua getter dan setter mengikuti konvensi penamaan.
sumber
foo.bar = biz.baz+5
akan memanggil fungsibiz
untuk mengevaluasibaz
, kemudian menambahkan lima untuk itu dan memanggil fungsi aktiffoo
untuk mengaturbar
ke nilai yang dihasilkan. Kelebihan seperti itu tidak disebut "properti", tetapi mereka dapat melayani tujuan yang sama.Ini bukan pendapat yang paling populer tetapi saya tidak melihat banyak perbedaan.
Setter dan getter adalah ide yang cukup buruk. Saya sudah memikirkannya dan jujur saya tidak bisa menemukan perbedaan antara setter / pengambil properti dan variabel publik dalam praktik.
Dalam TEORI setter dan pengambil atau properti menambahkan tempat untuk mengambil beberapa tindakan tambahan ketika variabel diatur / didapat dan secara teori mereka mengisolasi kode Anda dari perubahan.
Pada kenyataannya saya jarang melihat setter dan getter digunakan untuk menambahkan aksi, dan ketika Anda ingin menambahkan aksi Anda ingin menambahkannya ke SEMUA setter atau getter dari suatu kelas (seperti logging) yang seharusnya membuat Anda berpikir bahwa harus ada menjadi solusi yang lebih baik.
Adapun untuk mengisolasi keputusan desain, jika Anda mengubah int untuk waktu yang lama, Anda masih harus mengubah setter Anda dan setidaknya memeriksa setiap baris yang mengaksesnya dengan tangan - tidak banyak isolasi di sana.
Kelas yang tidak dapat diubah harus dihindari secara default, jadi menambahkan setter harus menjadi pilihan terakhir. Ini dimitigasi dengan pola pembangun di mana nilai dapat diatur hingga objek berada dalam keadaan yang diinginkan maka kelas bisa menjadi tidak berubah dan setter Anda akan melempar pengecualian.
Sedangkan untuk getter - saya masih tidak bisa membuat banyak perbedaan antara pengambil dan variabel final publik. Masalahnya di sini adalah bahwa OO buruk dalam kedua kasus. Anda seharusnya tidak meminta nilai dari objek dan mengoperasikannya - Anda harus meminta objek untuk melakukan operasi untuk Anda.
Omong-omong, saya sama sekali tidak mengadvokasi variabel publik - saya katakan setter dan getter (dan bahkan properti) terlalu dekat dengan variabel publik yang sudah ada.
Masalah besarnya adalah orang-orang yang bukan pemrogram OO terlalu tergoda untuk menggunakan setter dan getter untuk membuat objek menjadi bola-properti (struktur) yang diedarkan dan dioperasikan, cukup berlawanan dengan cara kerja kode Berorientasi Objek.
sumber
Pengguna getter dan setter masuk ke dalam prinsip enkapsulasi . Ini akan memungkinkan Anda untuk mengubah cara kerja di dalam kelas dan menjaga semuanya berfungsi.
Misalnya jika 3 objek lain memanggil
foo.bar
untuk mendapatkan nilai bar dan Anda memutuskan untuk mengubah nama bar sejauh Anda memiliki masalah di tangan Anda. Jika objek yang dipanggilfoo.bar
Anda harus mengubah semua kelas yang memiliki ini. Jika setter / pengambil digunakan maka Anda tidak perlu mengubah apa pun. Kemungkinan lain adalah mengubah jenis variabel yang hanya menambahkan beberapa kode transformasi ke pengambil / penyetel dan Anda baik-baik saja.sumber
Menggunakan getter dan setter juga memungkinkan Anda untuk mengontrol konten apa yang disimpan dalam variabel tertentu. Jika konten perlu jenis atau nilai tertentu, bagian dari kode penyetel Anda dapat memastikan bahwa nilai yang baru memenuhi persyaratan ini. Jika variabel bersifat publik, Anda tidak dapat memastikan persyaratan ini dipenuhi.
Pendekatan ini juga membuat kode Anda lebih mudah beradaptasi dan dikelola. Jauh lebih mudah untuk membuat perubahan pada arsitektur kelas jika Anda memiliki fungsi di tempat yang membuat arsitektur itu tersembunyi dari semua kelas lain atau fungsi yang memanfaatkan kelas itu. Perubahan nama variabel yang telah disebutkan hanyalah satu dari banyak perubahan yang lebih mudah dilakukan jika Anda memiliki fungsi seperti getter dan setter. Gagasan keseluruhan adalah untuk menjaga privasi sebanyak mungkin, terutama variabel kelas Anda.
sumber
Anda mengatakan "Satu-satunya kasus saya pikir Anda harus menggunakan getter dan setter adalah jika Anda perlu melakukan beberapa operasi selain set atau get."
Anda harus menggunakan getter dan setter jika pada suatu saat nanti Anda mungkin perlu melakukan beberapa operasi selain set dan get dan Anda tidak ingin mengubah ribuan baris kode sumber ketika itu terjadi.
Anda harus menggunakan getter dan setter jika Anda tidak ingin seseorang mengambil alamat variabel dan menyebarkannya, dengan konsekuensi yang merusak jika variabel itu kemudian dapat diubah tanpa kode sumber menyebutkannya, atau bahkan setelah objek berhenti ada lagi .
sumber
Pertama mari kita perjelas paradigma.
Di mana pengambil / penyetel berguna?
Apakah getter / setter berguna dalam Struktur Data? Tidak.
Struktur Data adalah spesifikasi tata letak memori yang umum dan dimanipulasi oleh sekumpulan fungsi.
Secara umum, setiap fungsi baru yang lama dapat muncul dan memanipulasi struktur data, jika ia melakukannya sedemikian rupa sehingga fungsi lainnya masih dapat memahaminya, maka fungsi tersebut bergabung dengan keluarga. Kalau tidak, ini adalah fungsi jahat dan sumber bug.
Jangan salah paham, mungkin ada beberapa keluarga fungsi yang berperang karena struktur data dengan snitch, turn-coats, dan agen ganda di mana-mana. Tidak apa-apa ketika mereka masing-masing memiliki struktur data sendiri untuk dimainkan, tetapi ketika mereka membagikannya ... bayangkan saja beberapa keluarga kriminal yang tidak setuju dengan politik, itu bisa menjadi kekacauan yang sangat cepat.
Mengingat kekacauan yang dapat dicapai fungsi keluarga, apakah ada cara untuk menyandikan struktur data sehingga fungsi jahat tidak mengacaukan semuanya? Ya, mereka disebut Objects.
Apakah getter / setter berguna di Objek? Tidak.
Inti dari membungkus struktur data di suatu objek adalah untuk memastikan bahwa tidak ada fungsi jahat yang bisa ada. Jika fungsi ingin bergabung dengan keluarga, itu harus diperiksa terlebih dahulu dan kemudian menjadi bagian dari objek.
Titik / tujuan pengambil dan penyetel adalah untuk memungkinkan fungsi di luar objek untuk mengubah tata letak memori objek secara langsung. Kedengarannya seperti pintu terbuka untuk mengizinkan penyamun ...
Kasus Tepi
Ada dua situasi ketika seorang pengambil / pembuat keputusan masuk akal.
Kontainer dan antarmuka wadah adalah contoh sempurna dari kedua situasi ini. Kontainer mengelola struktur data (daftar terkait, peta, pohon) secara internal tetapi dengan mudah mengendalikan elemen tertentu untuk semuanya. Antarmuka mengabstraksi hal ini dan mengabaikan implementasi sepenuhnya dan hanya menggambarkan harapan.
Sayangnya banyak implementasi yang salah dan mendefinisikan antarmuka objek semacam ini untuk memberikan akses langsung ke objek yang sebenarnya. Sesuatu seperti:
Ini rusak Implementasi Container harus secara eksplisit menyerahkan kontrol internal mereka kepada siapa pun yang menggunakannya. Saya belum melihat bahasa dengan nilai yang bisa berubah-ubah di mana ini baik-baik saja (bahasa dengan semantik bernilai tidak berubah secara definisi baik dari perspektif korupsi data, tetapi tidak harus dari perspektif mata-mata data).
Anda dapat meningkatkan / memperbaiki getter / setter dengan hanya menggunakan copy-semantik, atau dengan menggunakan proxy:
Bisa dibilang fungsi jahat masih bisa memainkan kekacauan di sini (dengan upaya yang cukup banyak hal yang mungkin), tetapi copy-semantik dan / atau proksi mengurangi kemungkinan sejumlah kesalahan.
Setter Pribadi / Setter
Ini adalah benteng getter dan setter terakhir yang bekerja pada tipe ini secara langsung. Sebenarnya saya bahkan tidak akan memanggil getter dan setter ini selain accessor dan manipulator.
Dalam konteks ini kadang-kadang memanipulasi bagian tertentu dari struktur data selalu / hampir selalu / umumnya membutuhkan pembukuan khusus untuk terjadi. Katakanlah ketika Anda memperbarui root dari pohon cache yang perlu disingkirkan harus dibersihkan, atau ketika Anda mengakses elemen data eksternal, kunci perlu diperoleh / dirilis. Dalam kasus ini masuk akal untuk menerapkan prinsip KERING dan membagi tindakan tersebut bersama-sama.
Dalam konteks pribadi, masih mungkin bagi fungsi-fungsi lain dalam keluarga untuk mengesampingkan 'getter dan setter' ini dan memanipulasi struktur data. Karena itu mengapa saya menganggap mereka lebih sebagai penentu dan manipulator. Anda dapat mengakses data secara langsung, atau mengandalkan anggota keluarga lain untuk mendapatkan bagian itu dengan benar.
Getters / Setters yang dilindungi
Dalam konteks yang dilindungi, tidak jauh berbeda dengan konteks publik. Fungsi asing yang mungkin ingin akses ke struktur data. Jadi tidak, jika mereka ada mereka beroperasi seperti pengambil / setter publik.
sumber
Dari pengalaman C ++, Setter / getter sangat membantu untuk 2 skenario:
Terlepas dari itu, keamanan adalah titik yang valid tetapi kepentingannya terbatas pada sangat sedikit aplikasi pengembangan seperti modul terkait akses masuk atau db. Mengapa repot-repot membuat kode tambahan ketika hanya sedikit orang yang menggunakan modul Anda?
sumber