Bagaimana Anda mengakses properti Objek dari dalam metode objek? [Tutup]

96

Apa cara "purist" atau "benar" untuk mengakses properti objek dari dalam metode objek yang bukan metode pengambil / penyetel?

Saya tahu bahwa dari luar objek Anda harus menggunakan getter / setter, tetapi dari dalam akan Anda lakukan:

Jawa:

String property = this.property;

PHP:

$property = $this->property;

atau apakah Anda akan melakukan:

Jawa:

String property = this.getProperty();

PHP:

$property = $this->getProperty();

Maafkan saya jika Java saya sedikit mati, sudah setahun sejak saya memprogram di Java ...

EDIT:

Sepertinya orang berasumsi bahwa saya hanya berbicara tentang variabel / properti pribadi atau dilindungi. Ketika saya mempelajari OO, saya diajari untuk menggunakan getter / setter untuk setiap properti bahkan jika itu adalah properti publik (dan sebenarnya saya diberitahu untuk tidak pernah membuat variabel / properti menjadi publik). Jadi, saya mungkin mulai dari asumsi yang salah sejak awal. Tampaknya orang-orang yang menjawab pertanyaan ini mungkin berkata bahwa Anda harus memiliki properti publik dan mereka yang tidak membutuhkan pengambil dan penyetel, yang bertentangan dengan apa yang diajarkan kepada saya, dan apa yang saya bicarakan, meskipun mungkin itu perlu dibahas sebagai baik. Itu mungkin topik yang bagus untuk pertanyaan yang berbeda ...

cmcculloh.dll
sumber

Jawaban:

62

Ini memiliki potensi perang agama, tetapi menurut saya jika Anda menggunakan pengambil / penyetel, Anda harus menggunakannya juga secara internal - menggunakan keduanya akan menyebabkan masalah pemeliharaan di masa mendatang (misalnya, seseorang menambahkan kode ke penyetel yang membutuhkan untuk menjalankan setiap kali properti itu disetel, dan properti itu disetel secara internal tanpa penyetel itu dipanggil).

Greg Hurlman
sumber
tidak melakukan hal lain dalam penyetel selain menyetel nilai properti sebagai contoh penggunaan yang salah di Java.
euforia83
1
@ euphoria83 Mungkin, tapi itu tidak menghalangi hal itu terjadi.
Greg Hurlman
Saya setuju dengan jawaban aslinya. Namun, ingatlah bahwa jika Anda menyetel atau mendapatkan sesuatu yang bersifat pribadi di dalam kelas atau objek, Anda perlu memastikan pengambil / penyetel tidak melakukan siklus atau berlebihan dalam beberapa cara yang menyebabkan kode Anda gagal. Jika Anda tidak dapat menggunakan pengambil / penyetel, akses langsung. (Mis. Pengambil / penyetel Anda mengakses metode sekunder (pribadi / dilindungi) untuk memanipulasi data.)
Rick Mac Gillis
43

Secara pribadi, saya merasa penting untuk tetap konsisten. Jika Anda memiliki getter dan setter, gunakanlah. Satu-satunya saat saya mengakses bidang secara langsung adalah saat pengakses memiliki banyak biaya tambahan. Ini mungkin terasa seperti Anda membengkakkan kode Anda secara tidak perlu, tetapi itu pasti bisa menghemat banyak sakit kepala di masa depan. Contoh klasik:

Nanti, Anda mungkin ingin mengubah cara kerja bidang itu. Mungkin itu harus dihitung dengan cepat atau mungkin Anda ingin menggunakan jenis yang berbeda untuk penyimpanan pendukung. Jika Anda mengakses properti secara langsung, perubahan seperti itu dapat merusak banyak kode dalam satu langkah besar.

MojoFilter
sumber
26

Saya cukup terkejut melihat betapa bulatnya sentimen itu gettersdan setter baik-baik saja dan baik. Saya menyarankan artikel pembakar oleh Allen Holub " Getters And Setters Are Evil ". Memang, judulnya untuk nilai kejutan, tetapi penulis membuat poin yang valid.

Pada dasarnya, jika Anda memiliki gettersdan settersuntuk setiap bidang privat, Anda menjadikan bidang tersebut sebaik publik. Anda akan sangat kesulitan untuk mengubah jenis bidang pribadi tanpa efek riak ke setiap kelas yang memanggilnya getter.

Selain itu, dari sudut pandang OO, objek harus merespons pesan (metode) yang sesuai dengan tanggung jawab tunggal mereka (mudah-mudahan). Sebagian besar gettersdan setterstidak masuk akal untuk objek konstituen mereka; Pen.dispenseInkOnto(Surface)lebih masuk akal bagi saya daripada Pen.getColor().

Getters dan setter juga mendorong pengguna kelas untuk meminta beberapa data dari objek, melakukan perhitungan, dan kemudian menetapkan beberapa nilai lain di objek, lebih dikenal sebagai pemrograman prosedural. Sebaiknya Anda hanya memberi tahu objek tersebut untuk melakukan apa yang akan Anda lakukan pada awalnya; juga dikenal sebagai idiom Ahli Informasi .

Getters dan setter, bagaimanapun, adalah kejahatan yang diperlukan di batas lapisan - UI, ketekunan, dan sebagainya. Akses terbatas ke internal kelas, seperti kata kunci teman C ++, akses dilindungi paket Java, akses internal .NET, dan Pola Kelas Teman dapat membantu Anda mengurangi visibilitas gettersdan penyetel hanya bagi mereka yang membutuhkannya.

moffdub
sumber
19

Tergantung bagaimana properti itu digunakan. Misalnya, Anda memiliki objek siswa yang memiliki properti nama. Anda bisa menggunakan metode Get untuk menarik nama dari database, jika belum diambil. Dengan cara ini Anda mengurangi panggilan yang tidak perlu ke database.

Sekarang katakanlah Anda memiliki penghitung integer pribadi di objek Anda yang menghitung berapa kali nama tersebut dipanggil. Anda mungkin ingin tidak menggunakan metode Dapatkan dari dalam objek karena itu akan menghasilkan hitungan yang tidak valid.

Shawn
sumber
Jika objek pelajar adalah objek bisnis / domain, Anda sekarang mencampur detail infrastruktur. Idealnya, objek bisnis / domain harus memperhatikan hanya dengan logika bisnis / domain.
moffdub
Bagaimana jika Anda menambahkan semacam boolean ke getter seperti: PHP: public function getName ($ outsideCall = true) {if ($ outsideCall) {$ this-> incrementNameCalled (); } return $ this-> name; } dan kemudian dari dalam Objek itu sendiri, jika Anda memanggil get name, Anda bisa membuatnya tidak bertambah dengan: PHP: $ name = $ this-> getName (false); Apakah saya terlalu berlebihan di sini?
cmcculloh
14

PHP menawarkan banyak cara untuk menangani ini, termasuk metode sulap __getdan __set, tetapi saya lebih suka getter dan setter eksplisit. Inilah alasannya:

  1. Validasi dapat ditempatkan di setter (dan getter dalam hal ini)
  2. Intellisense bekerja dengan metode eksplisit
  3. Tidak ada pertanyaan apakah properti itu hanya baca, tulis saja atau baca-tulis
  4. Mengambil properti virtual (yaitu, nilai terhitung) terlihat sama seperti properti biasa
  5. Anda bisa dengan mudah menyetel properti objek yang tidak pernah benar-benar ditentukan di mana pun, yang kemudian tidak terdokumentasi
Daging Tanpa Label
sumber
13

Apakah saya terlalu berlebihan di sini?

Mungkin;)

Pendekatan lain adalah menggunakan metode privat / dilindungi untuk benar-benar melakukan pengambilan (caching / db / etc), dan pembungkus publik untuk itu yang menambah hitungan:

PHP:

public function getName() {
    $this->incrementNameCalled();
    return $this->_getName();
}

protected function _getName() {
    return $this->name;
}

dan kemudian dari dalam objek itu sendiri:

PHP:

$name = $this->_getName();

Dengan cara ini Anda masih bisa menggunakan argumen pertama itu untuk sesuatu yang lain (seperti mengirim tanda apakah akan menggunakan data cache di sini atau tidak).

pix0r
sumber
12

Saya pasti kehilangan intinya di sini, mengapa Anda menggunakan getter di dalam objek untuk mengakses properti objek itu?

Mengambil kesimpulan ini pengambil harus memanggil pengambil, yang seharusnya disebut pengambil.

Jadi saya akan mengatakan di dalam metode objek mengakses properti secara langsung, terutama mengingat memanggil metode lain dalam objek itu (yang hanya akan mengakses properti secara langsung kemudian mengembalikannya) hanyalah latihan yang sia-sia dan sia-sia (atau apakah saya salah memahami pertanyaannya ).

Egg Vans
sumber
Saya didorong oleh kebutuhan yang sama seperti Anda harus berkomentar ... Ditambah itu dijawab tidak ditutup;)
Egg Vans
8

Cara OO yang murni adalah dengan menghindari keduanya dan mengikuti Hukum Demeter dengan menggunakan pendekatan Tell Don't Ask .

Alih-alih mendapatkan nilai properti objek, yang secara erat memasangkan dua kelas, gunakan objek sebagai parameter mis

  doSomethingWithProperty() {
     doSomethingWith( this.property ) ;
  }

Dimana propertinya adalah tipe asli, misalnya int, gunakan metode akses, beri nama untuk domain masalah bukan domain pemrograman.

  doSomethingWithProperty( this.daysPerWeek() ) ;

Ini akan memungkinkan Anda untuk mempertahankan enkapsulasi dan setiap kondisi pasca atau invarian yang bergantung. Anda juga dapat menggunakan metode penyetel untuk mempertahankan prasyarat atau invarian dependen, namun jangan terjebak dalam menamai mereka penyetel, kembali ke Prinsip Hollywood untuk penamaan saat menggunakan idiom.

Martin Spamer
sumber
8

Lebih baik menggunakan metode pengakses, bahkan di dalam objek. Inilah poin-poin yang langsung muncul di benak saya:

  1. Ini harus dilakukan untuk menjaga konsistensi dengan akses yang dibuat dari luar objek.

  2. Dalam beberapa kasus, metode pengakses ini dapat melakukan lebih dari sekadar mengakses bidang; mereka mungkin melakukan beberapa pemrosesan tambahan (ini jarang terjadi). Jika ini masalahnya, mengakses bidang secara langsung berarti Anda kehilangan pemrosesan tambahan itu, dan program Anda bisa salah jika pemrosesan ini selalu dilakukan selama akses tersebut.

Aadith Ramia
sumber
8

Jika yang Anda maksud adalah "sebagian besar enkapsulasi" oleh "purist", maka saya biasanya mendeklarasikan semua bidang saya sebagai pribadi dan kemudian menggunakan "bidang ini" dari dalam kelas itu sendiri. Untuk kelas lain, termasuk subclass, saya mengakses status instance menggunakan getter.

Allain Lalonde
sumber
7

Saya telah menemukan menggunakan setter / getter membuat kode saya lebih mudah dibaca. Saya juga menyukai kontrol yang diberikan saat kelas lain menggunakan metode dan jika saya mengubah data, properti akan menyimpan.

Brendon-Van-Heyzen
sumber
7

Bidang pribadi dengan properti publik atau dilindungi. Akses ke nilai harus melalui properti, dan disalin ke variabel lokal jika akan digunakan lebih dari sekali dalam suatu metode. Jika dan HANYA jika Anda memiliki sisa aplikasi Anda yang benar-benar di-tweak, diguncang, dan sebaliknya dioptimalkan ke tempat mengakses nilai dengan melalui properti asosciated mereka telah menjadi hambatan (Dan itu tidak akan pernah terjadi, saya jamin) jika Anda bahkan memulai untuk mempertimbangkan membiarkan apa pun selain properti menyentuh variabel pendukungnya secara langsung.

Pengembang .NET dapat menggunakan properti otomatis untuk menerapkan ini karena Anda bahkan tidak dapat melihat variabel pendukung pada waktu desain.

Mel
sumber
7

Tergantung. Ini lebih merupakan masalah gaya daripada apa pun, dan tidak ada aturan tegas.

Steve McLeod
sumber
7

Saya bisa salah karena saya autodidak, tetapi saya TIDAK PERNAH menggunakan properti publik di kelas Java saya, properti itu selalu bersifat pribadi atau dilindungi, sehingga kode luar harus diakses oleh pengambil / penyetel. Lebih baik untuk keperluan perawatan / modifikasi. Dan untuk kode kelas di dalam ... Jika metode pengambil sepele saya menggunakan properti secara langsung, tetapi saya selalu menggunakan metode penyetel karena saya dapat dengan mudah menambahkan kode ke peristiwa kebakaran jika saya mau.

Telcontar
sumber
7

Jika saya tidak mengedit properti, saya akan menggunakan metode publik get_property()kecuali jika itu adalah acara khusus seperti objek MySQLi di dalam objek lain di mana saya hanya akan membuat properti menjadi publik dan menyebutnya sebagai$obj->object_property .

Di dalam objek itu selalu $ this-> property untuk saya.

Ross
sumber
5

Nah, tampaknya dengan implementasi default properti C # 3.0, keputusan diambil untuk Anda; Anda HARUS menyetel properti menggunakan penyetel properti (mungkin pribadi).

Saya pribadi hanya menggunakan private member-behind ketika tidak melakukannya akan menyebabkan objek jatuh dalam keadaan yang kurang diinginkan, seperti saat menginisialisasi atau saat caching / lazy loading terlibat.

Coincoin
sumber
5

Saya suka jawaban dari cmcculloh , tapi sepertinya yang paling benar adalah jawaban dari Greg Hurlman . Gunakan pengambil / penyetel sepanjang waktu jika Anda mulai menggunakannya sejak awal dan / atau Anda terbiasa bekerja dengannya.

Selain itu, saya pribadi menemukan bahwa menggunakan getter / setter membuat kode lebih mudah dibaca dan di-debug nanti.

Robinho
sumber
4

Seperti yang dinyatakan dalam beberapa komentar: Terkadang Anda harus, terkadang tidak. Bagian terbaik dari variabel privat adalah Anda dapat melihat semua tempat variabel tersebut digunakan saat Anda mengubah sesuatu. Jika pengambil / penyetel Anda melakukan sesuatu yang Anda butuhkan, gunakanlah. Jika tidak masalah, Anda memutuskan.

Kasus sebaliknya dapat dibuat bahwa jika Anda menggunakan pengambil / penyetel dan seseorang mengubah pengambil / penyetel, mereka harus menganalisis semua tempat pengambil dan penyetel digunakan secara internal untuk melihat apakah itu mengacaukan sesuatu.

svrist
sumber