Apa keuntungan menggunakan getter dan setter - yang hanya mendapatkan dan mengatur - daripada hanya menggunakan bidang publik untuk variabel-variabel itu?
Jika getter dan setter pernah melakukan lebih dari sekedar get / set sederhana, saya bisa mengetahui ini dengan sangat cepat, tapi saya tidak 100% jelas tentang caranya:
public String foo;
lebih buruk dari:
private String foo;
public void setFoo(String foo) { this.foo = foo; }
public String getFoo() { return foo; }
Sedangkan yang pertama mengambil kode boilerplate jauh lebih sedikit.
Jawaban:
Sebenarnya ada banyak alasan bagus untuk mempertimbangkan menggunakan pengakses daripada langsung mengekspos bidang kelas - di luar argumen enkapsulasi dan membuat perubahan di masa depan lebih mudah.
Berikut adalah beberapa alasan yang saya ketahui:
sumber
public
metode accessor menyebabkan duplikasi kode, dan mengekspos informasi. Aksesor publik tidak diperlukan untuk menyusun (serialisasi). Dalam beberapa bahasa (Java),public
dapatkan aksesor tidak dapat memiliki tipe pengembalian diubah tanpa melanggar kelas dependen. Selain itu, saya percaya mereka bertentangan dengan prinsip-prinsip OO. Lihat juga: stackoverflow.com/a/1462424/59087plane.turnTo(dir); plane.setSpeed(spd); plane.setTargetAltitude(alt); plane.getBreaks().release();
saya ingin mengatakanplane.takeOff(alt)
. Apa bidang data dalam yang perlu diubah untuk memasukkan pesawat ketakingOff
mode tidak menjadi perhatian saya. Dan apa objek lain (breaks
) metode memberitahu saya juga tidak ingin tahu.Karena 2 minggu (bulan, tahun) dari sekarang ketika Anda menyadari bahwa setter Anda perlu melakukan lebih dari sekadar menetapkan nilai, Anda juga akan menyadari bahwa properti tersebut telah digunakan secara langsung di 238 kelas lainnya :-)
sumber
Bidang publik tidak lebih buruk daripada pasangan pengambil / penyetel yang tidak melakukan apa pun kecuali mengembalikan bidang dan menugaskannya. Pertama, jelas bahwa (dalam kebanyakan bahasa) tidak ada perbedaan fungsional. Perbedaan apa pun harus dalam faktor lain, seperti rawatan atau keterbacaan.
Keuntungan yang sering disebutkan dari pasangan pengambil / penyetel, tidak. Ada klaim ini bahwa Anda dapat mengubah implementasi dan klien Anda tidak perlu dikompilasi ulang. Seharusnya, setter membiarkan Anda menambahkan fungsionalitas seperti validasi di kemudian hari dan klien Anda bahkan tidak perlu mengetahuinya. Namun, menambahkan validasi ke setter adalah perubahan pada prasyaratnya, pelanggaran kontrak sebelumnya , yang, secara sederhana, "Anda dapat memasukkan apa pun di sini, dan Anda bisa mendapatkan hal yang sama nanti dari pengambil".
Jadi, sekarang setelah Anda melanggar kontrak, mengubah setiap file dalam basis kode adalah sesuatu yang harus Anda lakukan, bukan menghindari. Jika Anda menghindarinya, Anda membuat asumsi bahwa semua kode menganggap kontrak untuk metode itu berbeda.
Jika itu seharusnya bukan kontrak, maka antarmuka memungkinkan klien untuk meletakkan objek dalam keadaan tidak valid. Itu kebalikan dari enkapsulasi. Jika bidang itu tidak dapat benar-benar diatur ke apa pun dari awal, mengapa tidak ada validasi di sana sejak awal?
Argumen yang sama ini berlaku untuk keuntungan dugaan lain dari pasangan pengambil / penyetel pass-through ini: jika nanti Anda memutuskan untuk mengubah nilai yang ditetapkan, Anda melanggar kontrak. Jika Anda menimpa fungsionalitas default di kelas turunan, dengan cara di luar beberapa modifikasi yang tidak berbahaya (seperti logging atau perilaku tidak dapat diamati lainnya), Anda melanggar kontrak dari kelas dasar. Itu adalah pelanggaran terhadap Prinsip Pengganti Liskov, yang dipandang sebagai salah satu prinsip OO.
Jika suatu kelas memiliki para pengambil getah dan setter bodoh ini untuk setiap bidang, maka itu adalah kelas yang tidak memiliki invarian apa pun, tidak ada kontrak . Apakah itu benar-benar desain berorientasi objek? Jika semua kelas memiliki getter dan setter, itu hanya pemegang data bodoh, dan pemegang data bodoh harus terlihat seperti pemegang data bodoh:
Menambahkan pasangan pengambil / penyetel pass-through ke kelas semacam itu tidak menambah nilai. Kelas lain harus menyediakan operasi yang bermakna, bukan hanya operasi yang sudah disediakan bidang. Itulah cara Anda dapat mendefinisikan dan mempertahankan invarian yang bermanfaat.
Ada alasan untuk menggunakan getter dan setter, tetapi jika alasan itu tidak ada, membuat pasangan pengambil / penyetel atas nama dewa enkapsulasi palsu bukanlah hal yang baik. Alasan yang sah untuk membuat getter atau setter mencakup hal-hal yang sering disebutkan sebagai potensi perubahan yang dapat Anda buat nanti, seperti validasi atau representasi internal yang berbeda. Atau mungkin nilainya harus dibaca oleh klien tetapi tidak dapat ditulis (misalnya, membaca ukuran kamus), jadi pengambil sederhana adalah pilihan yang bagus. Tetapi alasan-alasan itu harus ada ketika Anda membuat pilihan, dan bukan hanya sebagai potensi yang Anda inginkan nanti. Ini adalah contoh dari YAGNI ( Kamu Tidak Akan Membutuhkannya ).
sumber
private
bidang. Jika suatu kelas tidak memiliki setter, mudah untuk membuatnya tidak berubah.Banyak orang berbicara tentang keuntungan dari getter dan setter tetapi saya ingin bermain sebagai penasihat iblis. Saat ini saya sedang men-debug program yang sangat besar di mana para programmer memutuskan untuk membuat semuanya getter dan setter. Itu mungkin tampak bagus, tapi itu mimpi buruk rekayasa terbalik.
Katakanlah Anda sedang mencari melalui ratusan baris kode dan Anda menemukan ini:
Ini hanya sepotong kode yang indah sampai Anda menyadari bahwa ini adalah setter. Sekarang, Anda mengikuti setter itu dan menemukan bahwa ia juga menetapkan person.firstName, person.lastName, person.isHuman, person.hasReallyCommonFirstName, dan memanggil person.update (), yang mengirimkan permintaan ke database, dll. Oh, itu di mana kebocoran memori Anda terjadi.
Memahami sepotong kode lokal pada pandangan pertama adalah sifat penting dari keterbacaan yang baik yang membuat getter dan setter cenderung rusak. Itulah sebabnya saya mencoba menghindarinya ketika saya bisa, dan meminimalkan apa yang mereka lakukan ketika saya menggunakannya.
sumber
person.name = "Joe";
dipanggil. Tidak ada cacat di jalan informasi, sintaks menyoroti menunjukkan itu bidang dan refactoring lebih sederhana (tidak perlu merefleksikan dua metode dan bidang). Kedua, semua siklus otak yang terbuang itu berpikir "getIsValid ()" atau seharusnya "isValid ()" dll. Dapat dilupakan. Saya tidak dapat memikirkan satu kali pun saya telah diselamatkan dari bug oleh pengambil / penyetel.Ada banyak alasan. Favorit saya adalah ketika Anda perlu mengubah perilaku atau mengatur apa yang dapat Anda atur pada variabel. Misalnya, katakan Anda memiliki metode setSpeed (kecepatan int). Tetapi Anda ingin bahwa Anda hanya dapat mengatur kecepatan maksimum 100. Anda akan melakukan sesuatu seperti:
Sekarang bagaimana jika DI MANA SAJA dalam kode Anda Anda menggunakan bidang publik dan kemudian Anda menyadari bahwa Anda membutuhkan persyaratan di atas? Bersenang-senang memburu setiap penggunaan bidang publik alih-alih hanya memodifikasi setter Anda.
2 sen saya :)
sumber
while(speed < 200) { do_something(); accelerate(); }
)myCar.setSpeed(157);
dan setelah beberapa barisspeed = myCar.getSpeed();
Dan sekarang ... Saya harap Anda senang men-debug sambil mencoba memahami mengapaspeed==100
harus157
Dalam dunia yang murni berorientasi objek, pengambil dan penentu adalah anti-pola yang mengerikan . Baca artikel ini: Getters / Setters. Jahat. Periode . Singkatnya, mereka mendorong programmer untuk berpikir tentang objek sebagai struktur data, dan jenis pemikiran ini murni prosedural (seperti dalam COBOL atau C). Dalam bahasa berorientasi objek tidak ada struktur data, tetapi hanya objek yang mengekspos perilaku (bukan atribut / properti!)
Anda dapat menemukan lebih banyak tentang mereka di Bagian 3.5 dari Objek Elegan (buku saya tentang pemrograman berorientasi objek).
sumber
new Dog()
bukan anjing. Ini adalah objek yang menyimpan informasi tentang seekor anjing. Dan untuk penggunaan itu, adalah wajar untuk dapat memperbaiki berat yang salah dicatat.Satu keuntungan dari pengakses dan mutator adalah Anda dapat melakukan validasi.
Misalnya, jika
foo
bersifat publik, saya dapat dengan mudah mengaturnyanull
dan kemudian orang lain dapat mencoba memanggil metode pada objek. Tapi itu sudah tidak ada lagi! DengansetFoo
metode, saya bisa memastikan bahwafoo
tidak pernah diaturnull
.Accessor dan mutators juga memungkinkan untuk enkapsulasi - jika Anda tidak seharusnya melihat nilai begitu ditetapkan (mungkin itu diatur dalam konstruktor dan kemudian digunakan oleh metode, tetapi tidak pernah seharusnya diubah), itu tidak akan pernah dilihat oleh siapa pun. Tetapi jika Anda dapat mengizinkan kelas lain untuk melihat atau mengubahnya, Anda dapat memberikan accessor dan / atau mutator yang tepat.
sumber
Tergantung pada bahasa Anda. Anda menandai ini "berorientasi objek" daripada "Java", jadi saya ingin menunjukkan bahwa jawaban ChssPly76 bergantung pada bahasa. Dalam Python, misalnya, tidak ada alasan untuk menggunakan getter dan setter. Jika Anda perlu mengubah perilaku, Anda dapat menggunakan properti, yang membungkus pengambil dan penyetel di sekitar akses atribut dasar. Sesuatu seperti ini:
sumber
obj.set_attr('foo')
) secara inheren lebih tinggi dari tanda sama dengan (obj.attr = 'foo'
). Akses publik adalah akses publik.obj.attr = 'foo'
hanya menetapkan variabel tanpa hal lain terjadiobj.setAttr('foo')
"set variabel saja tanpa ada yang terjadi"? Jika ini metode publik, maka itu metode publik. Jika Anda menggunakannya untuk mencapai beberapa efek samping, dan ini bersifat publik, maka Anda sebaiknya dapat mengandalkan segala sesuatu yang bekerja seolah-olah hanya efek samping yang dimaksud yang terjadi (dengan semua detail implementasi lainnya dan efek samping lainnya, penggunaan sumber daya, apa pun , disembunyikan dari kekhawatiran pengguna). Ini sama sekali tidak berbeda dengan Python. Sintaksis Python untuk mencapai efeknya lebih sederhana.Yah saya hanya ingin menambahkan bahwa meskipun kadang-kadang mereka diperlukan untuk enkapsulasi dan keamanan variabel Anda / objek, jika kita ingin kode Program Berorientasi Objek nyata, maka kita perlu BERHENTI MENGATASI AKSESORI , karena kadang-kadang kita sangat bergantung pada mereka ketika tidak benar-benar diperlukan dan itu membuat hampir sama seperti jika kita meletakkan variabel publik.
sumber
Terima kasih, itu benar-benar menjelaskan pemikiran saya. Sekarang inilah (hampir) 10 (hampir) alasan bagus untuk TIDAK menggunakan getter dan setter:
Tiga yang terakhir saya baru saja pergi (N / A atau D / C) ...
sumber
Saya tahu ini agak terlambat, tetapi saya pikir ada beberapa orang yang tertarik dengan kinerja.
Saya telah melakukan tes kinerja kecil. Saya menulis kelas "NumberHolder" yang, baik, memegang Integer. Anda dapat membaca Integer itu dengan menggunakan metode pengambil
anInstance.getNumber()
atau dengan langsung mengakses nomor dengan menggunakananInstance.number
. Program saya membaca angka 1.000.000.000 kali, melalui kedua cara. Proses itu diulang lima kali dan waktu dicetak. Saya mendapat hasil sebagai berikut:(Waktu 1 adalah jalan langsung, Waktu 2 adalah pengambil)
Soalnya, rajin (hampir) selalu sedikit lebih cepat. Kemudian saya mencoba dengan jumlah siklus yang berbeda. Alih-alih 1 juta, saya menggunakan 10 juta dan 0,1 juta. Hasil:
10 juta siklus:
Dengan 10 juta siklus, waktunya hampir sama. Berikut adalah 100 ribu (0,1 juta) siklus:
Juga dengan jumlah siklus yang berbeda, rajin rajin sedikit lebih cepat daripada cara biasa. Saya harap ini membantu Anda.
sumber
Jangan gunakan setter getter kecuali diperlukan untuk pengiriman Anda saat ini. Jangan berpikir terlalu banyak tentang apa yang akan terjadi di masa depan, jika ada hal yang diubah dengan permintaan perubahan di sebagian besar aplikasi produksi, sistem.
Berpikir sederhana, mudah, tambahkan kerumitan saat dibutuhkan.
Saya tidak akan mengambil keuntungan dari ketidaktahuan pemilik bisnis dengan pengetahuan teknis yang mendalam bagaimana hanya karena saya pikir itu benar atau saya suka pendekatannya.
Saya memiliki sistem besar yang ditulis tanpa setter getter hanya dengan pengubah akses dan beberapa metode untuk memvalidasi dan melakukan logika biz. Jika Anda benar-benar membutuhkannya. Gunakan apa saja.
sumber
Kami menggunakan getter dan setter:
Metode pengambil dan penyetel adalah antarmuka publik untuk mengakses anggota kelas privat.
Mantra enkapsulasi
Mantra enkapsulasi adalah membuat bidang pribadi dan metode publik.
Meskipun metode pengambil dan penyetel tidak menambahkan fungsi baru, kita dapat mengubah pikiran kita kembali nanti untuk membuat metode itu
Di mana pun nilai dapat digunakan, metode yang mengembalikan nilai itu dapat ditambahkan. Dari pada:
menggunakan
Dalam istilah awam
Misalkan kita perlu menyimpan detail ini
Person
. IniPerson
memiliki bidangname
,age
dansex
. Melakukan ini melibatkan menciptakan metode untukname
,age
dansex
. Sekarang jika kita perlu membuat orang lain, menjadi perlu untuk menciptakan metode untukname
,age
,sex
lagi.Daripada melakukan ini, kita dapat membuat kacang
class(Person)
dengan metode pengambil dan penyetel. Jadi besok kita bisa membuat objek dari Bean iniclass(Person class)
kapan saja kita perlu menambahkan orang baru (lihat gambar). Jadi kami menggunakan kembali bidang dan metode kelas kacang, yang jauh lebih baik.sumber
Saya menghabiskan cukup banyak waktu memikirkan ini untuk kasus Java, dan saya percaya alasan sebenarnya adalah:
Dengan kata lain, satu-satunya cara Anda dapat menentukan bidang dalam antarmuka adalah dengan menyediakan metode untuk menulis nilai baru dan metode untuk membaca nilai saat ini.
Metode-metode tersebut adalah pengambil dan pembuat ...
sumber
Ini bisa berguna untuk pemuatan malas. Katakanlah objek tersebut disimpan dalam database, dan Anda tidak ingin mendapatkannya kecuali Anda membutuhkannya. Jika objek diambil oleh pengambil, maka objek internal bisa nol sampai seseorang memintanya, maka Anda bisa mendapatkannya pada panggilan pertama ke pengambil.
Saya memiliki kelas halaman dasar dalam proyek yang diserahkan kepada saya yang memuat beberapa data dari beberapa panggilan layanan web yang berbeda, tetapi data dalam panggilan layanan web tersebut tidak selalu digunakan di semua halaman anak-anak. Layanan web, untuk semua manfaatnya, merintis definisi baru "lambat", jadi Anda tidak ingin membuat panggilan layanan web jika tidak perlu.
Saya pindah dari bidang publik ke getter, dan sekarang getter memeriksa cache, dan jika tidak ada, hubungi layanan web. Jadi dengan sedikit pembungkusan, banyak panggilan layanan web dicegah.
Jadi rajin rajin menyelamatkan saya dari mencoba mencari tahu, pada setiap halaman anak, apa yang saya butuhkan. Jika saya membutuhkannya, saya panggil pengambil, dan ia akan menemukannya untuk saya jika saya belum memilikinya.
sumber
Satu aspek yang saya lewatkan dalam jawaban sejauh ini, spesifikasi akses:
sumber
EDIT: Saya menjawab pertanyaan ini karena ada banyak orang yang belajar pemrograman menanyakan hal ini, dan sebagian besar jawabannya sangat kompeten secara teknis, tetapi mereka tidak mudah dimengerti jika Anda seorang pemula. Kami semua pemula, jadi saya pikir saya akan mencoba jawaban yang lebih ramah bagi pemula.
Dua yang utama adalah polimorfisme, dan validasi. Bahkan jika itu hanya struktur data yang bodoh.
Katakanlah kita memiliki kelas sederhana ini:
Kelas yang sangat sederhana yang menampung berapa banyak cairan di dalamnya, dan berapa kapasitasnya (dalam mililiter).
Apa yang terjadi ketika saya melakukannya:
Nah, Anda tidak akan berharap itu berhasil, bukan? Anda ingin ada semacam pemeriksaan kewarasan. Dan lebih buruknya, bagaimana jika saya tidak pernah menentukan kapasitas maksimum? Oh sayang, kami punya masalah.
Tapi ada masalah lain juga. Bagaimana jika botol hanya satu jenis wadah? Bagaimana jika kita memiliki beberapa wadah, semua dengan kapasitas dan jumlah cairan yang diisi? Jika kita bisa membuat antarmuka, kita bisa membiarkan sisa program kita menerima antarmuka itu, dan botol, jerigen dan segala macam hal hanya akan bekerja secara bergantian. Bukankah itu lebih baik? Karena metode permintaan antarmuka, ini juga merupakan hal yang baik.
Kami akan berakhir dengan sesuatu seperti:
Bagus! Dan sekarang kita hanya mengganti Botol dengan ini:
Saya akan meninggalkan definisi BottleOverflowException sebagai latihan untuk pembaca.
Sekarang perhatikan betapa kuatnya ini. Kami dapat menangani semua jenis wadah dalam kode kami sekarang dengan menerima LiquidContainer, bukan Botol. Dan bagaimana botol-botol ini menangani hal-hal semacam ini bisa berbeda. Anda dapat memiliki botol yang menuliskan statusnya ke disk saat berubah, atau botol yang menghemat database SQL atau GNU tahu apa lagi.
Dan semua ini dapat memiliki cara berbeda untuk menangani berbagai waria. Botol hanya memeriksa dan jika meluap, ia melempar RuntimeException. Tapi itu mungkin hal yang salah untuk dilakukan. (Ada diskusi yang bermanfaat untuk dilakukan tentang penanganan kesalahan, tapi saya sengaja membuatnya sangat sederhana di sini. Orang-orang dalam komentar kemungkinan akan menunjukkan kekurangan dari pendekatan sederhana ini;;))
Dan ya, sepertinya kita beralih dari ide yang sangat sederhana untuk mendapatkan jawaban yang jauh lebih baik dengan cepat.
Harap dicatat juga bahwa Anda tidak dapat mengubah kapasitas botol. Sekarang diatur di atas batu. Anda bisa melakukan ini dengan int dengan menyatakannya final. Tetapi jika ini adalah daftar, Anda dapat mengosongkannya, menambahkan hal-hal baru ke dalamnya, dan seterusnya. Anda tidak dapat membatasi akses untuk menyentuh jeroan.
Ada juga hal ketiga yang tidak semua orang atasi: getter dan setter menggunakan panggilan metode. Itu berarti mereka terlihat seperti metode normal di tempat lain. Alih-alih memiliki sintaks khusus aneh untuk DTO dan yang lainnya, Anda memiliki hal yang sama di mana-mana.
sumber
Dalam bahasa yang tidak mendukung "properti" (C ++, Java) atau memerlukan kompilasi ulang klien saat mengubah bidang ke properti (C #), menggunakan metode get / set lebih mudah untuk dimodifikasi. Misalnya, menambahkan logika validasi ke metode setFoo tidak akan perlu mengubah antarmuka publik kelas.
Dalam bahasa yang mendukung properti "nyata" (Python, Ruby, mungkin Smalltalk?) Tidak ada gunanya untuk mendapatkan / mengatur metode.
sumber
Salah satu prinsip dasar desain OO: Enkapsulasi!
Ini memberi Anda banyak manfaat, salah satunya adalah Anda dapat mengubah implementasi pengambil / penyetel di belakang layar tetapi konsumen mana pun dari nilai itu akan terus bekerja selama tipe datanya tetap sama.
sumber
Anda harus menggunakan getter dan setter saat:
Jadi ini jarang sekali pertanyaan OO umum; itu adalah pertanyaan khusus bahasa, dengan jawaban berbeda untuk bahasa yang berbeda (dan berbagai kasus penggunaan).
Dari sudut pandang teori OO, getter dan setters tidak berguna. Antarmuka kelas Anda adalah fungsinya, bukan seperti apa kondisinya. (Jika tidak, Anda telah menulis kelas yang salah.) Dalam kasus yang sangat sederhana, di mana apa yang dilakukan kelas adalah adil, misalnya, mewakili titik dalam koordinat persegi panjang, * atribut adalah bagian dari antarmuka; getter dan setter hanya cloud itu. Tetapi dalam hal apa pun kecuali kasus yang sangat sederhana, baik atribut maupun getter dan setter bukan bagian dari antarmuka.
Dengan kata lain: Jika Anda percaya bahwa konsumen kelas Anda seharusnya tidak tahu bahwa Anda memiliki
spam
atribut, apalagi dapat mengubahnya dengan sendirinya, maka memberi merekaset_spam
metode adalah hal terakhir yang ingin Anda lakukan.* Bahkan untuk kelas sederhana itu, Anda mungkin tidak perlu ingin mengizinkan pengaturan
x
dany
nilai - nilai. Jika ini benar-benar kelas, tidak harus itu memiliki metode sepertitranslate
,rotate
, dll? Jika hanya kelas karena bahasa Anda tidak memiliki catatan / struct / nama tupel, maka ini bukan pertanyaan OO ...Tapi tidak ada yang pernah melakukan desain OO umum. Mereka melakukan desain, dan implementasi, dalam bahasa tertentu. Dan dalam beberapa bahasa, getter dan setter jauh dari tidak berguna.
Jika bahasa Anda tidak memiliki properti, maka satu-satunya cara untuk mewakili sesuatu yang secara konseptual adalah atribut, tetapi sebenarnya dihitung, atau divalidasi, dll., Adalah melalui pengambil dan setter.
Bahkan jika bahasa Anda memang memiliki properti, mungkin ada kasus di mana bahasa tersebut tidak memadai atau tidak sesuai. Misalnya, jika Anda ingin membolehkan subkelas untuk mengontrol semantik atribut, dalam bahasa tanpa akses dinamis, subkelas tidak dapat menggantikan properti yang dikomputasi untuk atribut.
Adapun "bagaimana jika saya ingin mengubah implementasi saya nanti?" pertanyaan (yang diulang beberapa kali dalam susunan kata yang berbeda dalam pertanyaan OP dan jawaban yang diterima): Jika itu benar-benar perubahan implementasi murni, dan Anda mulai dengan atribut, Anda dapat mengubahnya ke properti tanpa mempengaruhi antarmuka. Kecuali, tentu saja, bahasa Anda tidak mendukung itu. Jadi ini benar-benar kasus yang sama lagi.
Juga, penting untuk mengikuti idiom bahasa (atau kerangka kerja) yang Anda gunakan. Jika Anda menulis kode gaya Ruby yang indah di C #, pengembang C # berpengalaman selain Anda akan kesulitan membacanya, dan itu buruk. Beberapa bahasa memiliki budaya yang lebih kuat di sekitar konvensi mereka daripada yang lain. — dan mungkin bukan kebetulan bahwa Jawa dan Python, yang berada di ujung yang berlawanan dari spektrum untuk bagaimana getter idiomatik, kebetulan memiliki dua budaya terkuat.
Di luar pembaca manusia, akan ada perpustakaan dan alat yang mengharapkan Anda untuk mengikuti kebaktian, dan membuat hidup Anda lebih sulit jika tidak. Mengaitkan widget Builder Interface ke apa pun selain properti ObjC, atau menggunakan perpustakaan Java mengejek tertentu tanpa getter, hanya membuat hidup Anda lebih sulit. Jika alat itu penting bagi Anda, jangan melawannya.
sumber
Dari sudut pandang desain orientasi objek, kedua alternatif dapat merusak pemeliharaan kode dengan melemahkan enkapsulasi kelas. Untuk diskusi, Anda dapat melihat artikel yang luar biasa ini: http://typicalprogrammer.com/?p=23
sumber
Metode getter dan setter adalah metode accessor, artinya mereka umumnya merupakan antarmuka publik untuk mengubah anggota kelas privat. Anda menggunakan metode pengambil dan penyetel untuk menentukan properti. Anda mengakses metode pengambil dan penyetel sebagai properti di luar kelas, meskipun Anda mendefinisikannya di dalam kelas sebagai metode. Properti-properti di luar kelas dapat memiliki nama yang berbeda dari nama properti di kelas.
Ada beberapa keuntungan menggunakan metode pengambil dan penyetel, seperti kemampuan untuk membiarkan Anda membuat anggota dengan fungsionalitas canggih yang dapat Anda akses seperti properti. Mereka juga memungkinkan Anda membuat properti hanya-baca dan menulis-saja.
Meskipun metode pengambil dan penyetel berguna, Anda harus berhati-hati untuk tidak menggunakannya secara berlebihan karena, di antara masalah lain, mereka dapat membuat pemeliharaan kode lebih sulit dalam situasi tertentu. Juga, mereka menyediakan akses ke implementasi kelas Anda, seperti anggota publik. Praktik OOP menghambat akses langsung ke properti dalam kelas.
Ketika Anda menulis kelas, Anda selalu didorong untuk membuat sebanyak mungkin variabel instan Anda menjadi pribadi dan menambahkan metode pengambil dan penyetel yang sesuai. Ini karena ada beberapa kali ketika Anda mungkin tidak ingin membiarkan pengguna mengubah variabel tertentu dalam kelas Anda. Misalnya, jika Anda memiliki metode statis pribadi yang melacak jumlah instance yang dibuat untuk kelas tertentu, Anda tidak ingin pengguna memodifikasi penghitung itu menggunakan kode. Hanya pernyataan konstruktor yang harus menambah variabel itu setiap kali dipanggil. Dalam situasi ini, Anda dapat membuat variabel instance pribadi dan mengizinkan metode pengambil hanya untuk variabel penghitung, yang berarti pengguna dapat mengambil nilai saat ini hanya dengan menggunakan metode pengambil, dan mereka tidak akan dapat menetapkan nilai baru menggunakan metode setter.
sumber
Kode berkembang .
private
sangat bagus untuk ketika Anda membutuhkan perlindungan anggota data . Akhirnya semua kelas harus berupa "miniprogram" yang memiliki antarmuka yang terdefinisi dengan baik sehingga Anda tidak bisa mengacaukan internalnya .Yang mengatakan, pengembangan perangkat lunak bukan tentang menetapkan versi akhir kelas seolah-olah Anda menekan beberapa patung besi pada percobaan pertama. Saat Anda bekerja dengannya, kode lebih seperti tanah liat. Ini berkembang saat Anda mengembangkannya dan mempelajari lebih lanjut tentang domain masalah yang Anda selesaikan. Selama kelas pengembangan dapat berinteraksi satu sama lain dari yang seharusnya (ketergantungan Anda berencana faktor keluar), bergabung bersama, atau berpisah. Jadi saya pikir perdebatan bermuara pada orang-orang yang tidak ingin menulis secara religius
Jadi kamu punya:
Dari pada
Tidak hanya
getVar()
berisik secara visual, ini memberikan ilusi yanggettingVar()
entah bagaimana merupakan proses yang lebih kompleks daripada yang sebenarnya. Bagaimana Anda (sebagai penulis kelas) menganggap kesucianvar
ini sangat membingungkan bagi pengguna kelas Anda jika memiliki passthru setter - maka sepertinya Anda memasang gerbang ini untuk "melindungi" sesuatu yang Anda anggap berharga, (kesucian darivar
) tetapi bahkan Anda mengakuivar
perlindungan tidak banyak berarti dengan kemampuan bagi siapa pun untuk hanya masuk danset
var
untuk nilai apa pun yang mereka inginkan, tanpa Anda bahkan mengintip apa yang mereka lakukan.Jadi saya memprogram sebagai berikut (dengan asumsi pendekatan tipe "gesit" - yaitu ketika saya menulis kode tidak tahu persis apa yang akan dilakukan / tidak punya waktu atau pengalaman untuk merencanakan set antarmuka gaya air terjun yang rumit):
1) Mulai dengan semua anggota publik untuk objek dasar dengan data dan perilaku. Inilah sebabnya mengapa dalam semua kode "contoh" C ++ saya akan melihat saya menggunakan
struct
alih-alih diclass
mana - mana.2) Ketika perilaku internal suatu objek untuk anggota data menjadi cukup kompleks, (misalnya, ia suka menjaga internal
std::list
dalam beberapa jenis urutan), fungsi tipe pengaksesor ditulis. Karena saya pemrograman sendiri, saya tidak selalu mengatur anggota secaraprivate
langsung, tetapi di suatu tempat evolusi kelas anggota akan "dipromosikan" ke salah satuprotected
atauprivate
.3) Kelas yang sepenuhnya diubah dan memiliki aturan ketat tentang internal mereka (yaitu mereka tahu persis apa yang mereka lakukan, dan Anda tidak boleh "bercinta" (istilah teknis) dengan internalnya) diberi
class
penunjukan, anggota pribadi default, dan hanya beberapa anggota terpilih yang diizinkanpublic
.Saya menemukan pendekatan ini memungkinkan saya untuk menghindari duduk di sana dan menulis rajin rajin / giat ketika banyak anggota data bermigrasi keluar, bergeser sekitar, dll selama tahap awal evolusi kelas.
sumber
Ada alasan bagus untuk mempertimbangkan menggunakan pengakses adalah tidak ada warisan properti. Lihat contoh berikut:
Keluaran:
sumber
Getters dan setters digunakan untuk mengimplementasikan dua aspek mendasar dari Pemrograman Berorientasi Objek yaitu:
Misalkan kita memiliki kelas Karyawan:
Di sini rincian implementasi Nama Lengkap disembunyikan dari pengguna dan tidak dapat diakses langsung ke pengguna, tidak seperti atribut publik.
sumber
Satu kegunaan lain (dalam bahasa yang mendukung properti) adalah bahwa setter dan getter dapat menyiratkan bahwa operasi adalah non-sepele. Biasanya, Anda ingin menghindari melakukan apa pun yang mahal secara komputasi di sebuah properti.
sumber
execute
atau harga yang mahalbuild
.Satu keuntungan relatif modern dari pengambil / setter adalah membuatnya lebih mudah untuk menelusuri kode dalam editor kode yang ditandai (diindeks). Misalnya. Jika Anda ingin melihat siapa yang menetapkan anggota, Anda dapat membuka hierarki panggilan penyetel.
Di sisi lain, jika anggota bersifat publik, alat tidak memungkinkan untuk memfilter akses baca / tulis ke anggota. Jadi, Anda harus berjalan dengan susah payah melalui semua penggunaan anggota.
sumber
Dalam bahasa berorientasi objek, metode, dan pengubah aksesnya, menyatakan antarmuka untuk objek itu. Antara konstruktor dan metode accessor dan mutator adalah mungkin bagi pengembang untuk mengontrol akses ke keadaan internal suatu objek. Jika variabel hanya dinyatakan publik maka tidak ada cara untuk mengatur akses itu. Dan ketika kita menggunakan setter kita dapat membatasi pengguna untuk input yang kita butuhkan. Berarti umpan untuk variabel tersebut akan datang melalui saluran yang tepat dan saluran sudah ditentukan oleh kami. Jadi lebih aman menggunakan setter.
sumber
Selain itu, ini untuk "bukti masa depan" kelas Anda. Secara khusus, mengubah dari bidang ke properti adalah jeda ABI, jadi jika Anda kemudian memutuskan bahwa Anda membutuhkan lebih banyak logika daripada hanya "mengatur / mendapatkan bidang", maka Anda perlu memecahkan ABI, yang tentu saja menimbulkan masalah untuk apa pun lain sudah dikompilasi dengan kelas Anda.
sumber
Saya hanya ingin membuang gagasan anotasi: @getter dan @setter. Dengan @getter, Anda harus dapat obj = class.field tetapi tidak class.field = obj. Dengan @setter, dan sebaliknya. Dengan @getter dan @setter Anda harus dapat melakukan keduanya. Ini akan menjaga enkapsulasi dan mengurangi waktu dengan tidak memanggil metode sepele saat runtime.
sumber