Akses bidang pribadi objek lain di kelas yang sama

91
class Person 
{
   private BankAccount account;

   Person(BankAccount account)
   {
      this.account = account;
   }

   public Person someMethod(Person person)
   {
     //Why accessing private field is possible?

     BankAccount a = person.account;
   }
}

Tolong lupakan desainnya. Saya tahu bahwa OOP menentukan bahwa objek pribadi bersifat pribadi untuk kelas. Pertanyaan saya adalah, mengapa OOP dirancang sedemikian rupa sehingga bidang privat memiliki akses tingkat kelas dan bukan akses tingkat objek ?

Nageswaran
sumber
5
Saya yakin OP menganggap objek "Person" yang diteruskan ke "someMethod" sebagai objek terpisah, dan oleh karena itu metode tersebut seharusnya tidak memiliki akses ke anggota privatnya ... meskipun itu dalam kelas "Person".
Inisheer
1
Beberapa bahasa tidak melakukan ini (Newspeak misalnya). Anda tidak mungkin mendapatkan jawaban yang bagus tentang mengapa. Anda akan mendapatkan jawaban yang bekerja mundur dari apa yang kebetulan ditentukan.
Tom Hawtin - tackline
Ini someMethodtidak valid. Itu tidak mengembalikan apapun. Itu pasti void.
Nicolas Barbulesco
1
Jika ini tidak terjadi, akan sangat sulit untuk menulis copy konstruktor dan operator penugasan imo.
rozina

Jawaban:

70

Saya juga agak penasaran dengan jawabannya.

Jawaban paling memuaskan yang saya temukan adalah dari Artemix di posting lain di sini (Saya mengganti nama AClass dengan kelas Person): Mengapa pengubah akses tingkat kelas daripada tingkat objek?

Pengubah privat memberlakukan prinsip Enkapsulasi.

Idenya adalah bahwa 'dunia luar' seharusnya tidak membuat perubahan pada proses internal Person karena implementasi Person dapat berubah seiring waktu (dan Anda harus mengubah seluruh dunia luar untuk memperbaiki perbedaan dalam implementasi - yang hampir mustahil).

Ketika instance Person mengakses internal instance Person lainnya - Anda dapat yakin bahwa kedua instance selalu mengetahui detail implementasi Person. Jika logika proses internal ke Person diubah - yang harus Anda lakukan hanyalah mengubah kode Person.

EDIT: Silakan pilih jawaban Artemix. Saya hanya menyalin-tempelnya.

Iwan Satria
sumber
4
Ini mungkin alasannya. Tapi ini ide yang buruk . Ini mendorong praktik yang buruk. Seorang pengembang yang mengakses bidang Person, di dalam kelas Person, tidak harus mengetahui implementasi seluruh kelas. Praktik yang baik adalah menggunakan pengakses, tanpa harus mengetahui operasi apa yang dilakukan pengakses.
Nicolas Barbulesco
16
@NicolasBarbulesco Saya pikir alasan yang diberikan dalam jawaban itu masuk akal. Katakanlah misalnya Anda ingin mengimplementasikan equals(Object)metode di kelas Java untuk memeriksa kesetaraan Personobjek dengan instance lain Person. Anda mungkin ingin mengaktifkan dunia luar untuk memeriksa apakah kedua contoh tersebut sama, tetapi Anda mungkin tidak ingin mengekspos semua bidang privat kelas yang diperlukan untuk memeriksa kesetaraan ke dunia luar menggunakan metode pengakses publik. Memiliki akses tingkat kelas ke privatebidang memungkinkan penerapan metode seperti itu tanpa adanya kebutuhan untuk mengimplementasikan metode publik tersebut.
Malte Skoruppa
1
@MalteSkoruppa - Ini adalah contoh yang bagus (mengimplementasikan metode equals).
Nicolas Barbulesco
@MalteSkoruppa - Namun, menerapkan metode ini equalsdapat dilakukan dengan memanggil pengakses pribadi.
Nicolas Barbulesco
@NicolasBarbulesco Ya tentu saja, tetapi intinya adalah, apakah Anda menggunakan pengakses pribadi atau mengakses langsung bidang pribadi untuk mengimplementasikan metode, privateharus memberikan akses tingkat kelas. Saya setuju bahwa menggunakan pengakses umumnya merupakan kebiasaan yang baik, meskipun dalam hal ini sebagian besar adalah masalah konteks dan gaya pribadi. Perhatikan bahwa Joshua Bloch di Java Efektif (item 8) dan Tal Cohen di artikel Dr. Dobbs ini secara langsung mengakses bidang pribadi di daftar kode mereka saat membahas cara menerapkan equals.
Malte Skoruppa
17

Lihat Spesifikasi Bahasa Java, Bagian 6.6.1. Menentukan Aksesibilitas

Ini menyatakan

Sebaliknya, jika anggota atau konstruktor dideklarasikan private, maka akses diizinkan jika dan hanya jika itu terjadi dalam tubuh kelas tingkat atas (§7.6) yang membungkus deklarasi anggota atau konstruktor.

Klik link di atas untuk lebih jelasnya. Jadi jawabannya adalah: Karena James Gosling dan penulis Java lainnya memutuskan demikian.

jlordo
sumber
17

Pertanyaan bagus. Tampaknya pengubah akses tingkat objek akan memberlakukan prinsip Enkapsulasi lebih jauh.

Tapi sebenarnya yang terjadi adalah sebaliknya. Mari kita ambil contoh. Misalkan Anda ingin menyalin jauh objek dalam konstruktor, jika Anda tidak dapat mengakses anggota pribadi objek itu. Maka satu-satunya cara yang mungkin adalah menambahkan beberapa pengakses publik ke semua anggota pribadi. Ini akan membuat objek Anda telanjang ke semua bagian lain dari sistem.

Jadi enkapsulasi tidak berarti tertutup bagi seluruh dunia. Itu berarti menjadi selektif tentang siapa yang Anda ingin terbuka.

Wei Qiu
sumber
2
Jawaban ini perlu dipilih! Jawaban lain hanya menyatakan kembali 'aturan' tetapi hanya jawaban ini yang benar-benar mengungkapkan alasan di balik aturan tersebut dan tepat sasaran.
mzoz
4
Tapi bukankah lebih baik jika sebuah objek bertanggung jawab untuk menyediakan salinannya sendiri? Kemudian, jika Anda membutuhkan salinan mendalam dari suatu objek, tidak masalah jika Anda adalah objek lain dari kelas yang sama atau objek dari kelas yang berbeda: itu mekanisme yang sama, o.deepCopy()atau apa pun.
dirtside
4

Ini berfungsi karena Anda berada di class Person- kelas diizinkan untuk menyodok di dalam jenis kelasnya sendiri. Ini sangat membantu ketika Anda ingin menulis konstruktor salinan, misalnya:

class A
{
   private:
      int x;
      int y;
   public:
      A(int a, int b) x(a), y(b) {}
      A(A a) { x = a.x; y = y.x; }
};

Atau jika kita ingin menulis operator+dan operator-untuk kelas angka besar kita.

Mats Petersson
sumber
Ini mirip dengan injeksi ketergantungan. Di mana Anda juga dapat memasukkan objek kelas lain, di mana Anda tidak dapat mengakses variabel privat.
Nageswaran
Tentu, jika Anda mencoba membangun kelas A dari objek kelas B, dan B memiliki komponen privat, maka A perlu dideklarasikan sebagai teman, atau hanya dapat melihat bagian publik [mungkin dilindungi, jika A diturunkan dari B ].
Mats Petersson
Di java dan .net tidak ada konsep sobat. Dalam kasus seperti itu, bagaimana menangani ini?
Nageswaran
1

Hanya 2 sen saya pada pertanyaan mengapa semantik visibilitas pribadi di Jawa adalah tingkat kelas daripada tingkat objek.

Saya akan mengatakan bahwa kenyamanan tampaknya menjadi kuncinya di sini. Faktanya, visibilitas pribadi di tingkat objek akan memaksa untuk mengekspos metode ke kelas lain (misalnya dalam paket yang sama) dalam skenario yang diilustrasikan oleh OP.

Sebenarnya saya tidak dapat membuat atau menemukan contoh yang menunjukkan bahwa visibilitas di tingkat kelas-privat (seperti yang ditawarkan oleh Java) menciptakan masalah apa pun jika dibandingkan dengan visibilitas di tingkat objek-pribadi.

Meskipun demikian, bahasa pemrograman dengan sistem kebijakan visibilitas yang lebih terperinci dapat memberikan visibilitas objek pada level objek dan level kelas.

Misalnya Eiffel , menawarkan ekspor selektif: Anda dapat mengekspor fitur kelas apa pun ke kelas apa pun pilihan Anda, dari {NONE} (object-private) hingga {ANY} (setara dengan publik, dan juga default), ke {PERSON} (kelas-pribadi, lihat contoh OP), untuk kelompok kelas tertentu {PERSON, BANK}.

Menarik juga untuk berkomentar bahwa di Eiffel Anda tidak perlu membuat atribut menjadi pribadi dan menulis getter untuk mencegah kelas lain menetapkannya. Atribut publik di Eiffel secara default dapat diakses dalam mode hanya-baca, jadi Anda tidak memerlukan pengambil hanya untuk mengembalikan nilainya.

Tentu saja Anda masih memerlukan penyetel untuk menyetel atribut, tetapi Anda dapat menyembunyikannya dengan mendefinisikannya sebagai "pemberi tugas" untuk atribut itu. Ini memungkinkan Anda, jika ingin, menggunakan operator penetapan yang lebih nyaman daripada pemanggilan penyetel.

Temp Agilist
sumber
0

Karena private pengubah akses membuatnya hanya terlihat di dalam kelas . Metode ini masih DI dalam kelas .

darijan
sumber
Pertanyaan saya adalah mengapa itu dirancang seperti "di dalam kelas" tetapi mengapa tidak seperti "hanya di dalam objek"?
Nageswaran
Karena begitulah java dibuat.
darijan
Dan kenapa java membuat java seperti itu?
Nageswaran
Java tidak membuatnya, pencipta Java yang membuatnya. Mengapa? Karena mereka keren!
darijan
1
Pembuat Java tidak akan melakukannya tanpa alasan apa pun, dan pasti ada alasan untuk melakukannya; Saya menanyakan alasannya
Nageswaran
0

yang privatebidang diakses di kelas / objek di mana lapangan dinyatakan. Ini bersifat pribadi untuk kelas / objek lain di luar tempatnya berada.

ola
sumber
-1

Hal pertama di sini yang harus kita pahami adalah yang harus kita lakukan adalah harus mengikuti prinsip-prinsip oops sehingga enkapsulasi mengatakan bahwa membungkus data dalam paket (yaitu kelas) dan kemudian merepresentasikan semua data sebagai Object dan mudah diakses. jadi jika kita membuat field sebagai non-private daripada diakses secara indivisual. dan itu menghasilkan paratice yang buruk.

Sachin Jadhav
sumber