Aynı sınıftaki başka bir nesnenin özel alanına erişim


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;
   }
}

Lütfen tasarımı unutun. OOP'nin özel nesnelerin sınıfa özel olduğunu belirttiğini biliyorum. Sorum şu, OOP neden özel alanların nesne düzeyinde erişime sahip değil , sınıf düzeyinde erişime sahip olacak şekilde tasarlandı ?


5
OP'nin "someMethod" a aktarılan "Kişi" nesnesini ayrı bir nesne olarak gördüğüne inanıyorum ve bu nedenle yöntemin "Kişi" sınıfında olsa bile özel üyelerine erişimi olmamalıdır.
Inisheer

1
Bazı diller bunu yapmaz (örneğin Newspeak). Neden olduğuna dair iyi bir cevap alamayacaksın. Belirtilenlerden geriye doğru çalışan yanıtlar alacaksınız.
Tom Hawtin - tackline

someMethodGeçerli değil. Hiçbir şey döndürmez. Olmalı void.
Nicolas Barbulesco

1
Durum böyle olmasaydı, kopya yapıcı ve atama operatörü imo yazmak çok zor olurdu.
rozina

Yanıtlar:


70

Ben de cevabı biraz merak ediyorum.

Bulduğum en tatmin edici yanıt, buradaki başka bir gönderide Artemix'ten geliyor (AClass'ı Person sınıfıyla yeniden adlandırıyorum): Neden nesne düzeyi yerine sınıf düzeyinde erişim değiştiricileri var?

Özel değiştirici, Kapsülleme ilkesini uygular.

Buradaki fikir, 'dış dünyanın' Kişinin iç süreçlerinde değişiklik yapmaması gerektiğidir çünkü Kişi uygulaması zamanla değişebilir (ve uygulamadaki farklılıkları düzeltmek için tüm dış dünyayı değiştirmeniz gerekir - ki bu neredeyse imkansızdır).

Person örneği diğer Person örneğinin dahili öğelerine eriştiğinde - her iki örneğin de Person uygulamasının ayrıntılarını her zaman bildiğinden emin olabilirsiniz. Kişiye dahili işlemlerin mantığı değiştirilirse - tek yapmanız gereken Kişi kodunu değiştirmektir.

DÜZENLEME: Lütfen Artemix'in cevabına oy verin. Ben sadece kopyalayıp yapıştırıyorum.


4
Muhtemelen nedeni budur. Ama bu kötü bir fikir . Bu kötü uygulamayı teşvik eder. PersonSınıftaki bir alanına erişen bir geliştiricinin Person, tüm sınıfın uygulanmasını bilmesine gerek yoktur. İyi uygulama, erişimcinin hangi işlemleri yaptığını bilmeden erişimciyi kullanmaktır.
Nicolas Barbulesco

16
@NicolasBarbulesco Cevapta verilen nedenin sağlam olduğunu düşünüyorum. Örneğin equals(Object)bir Personnesnenin eşitliğini başka bir örneğiyle kontrol etmek için yöntemi bir Java sınıfında uygulamak istediğinizi varsayalım Person. Dış dünyanın iki durumun eşit olup olmadığını kontrol etmesini sağlamak isteyebilirsiniz, ancak eşitliği dış dünyaya açık erişimci yöntemlerini kullanarak kontrol etmek için gerekli tüm sınıfın özel alanlarını açığa çıkarmak istemeyebilirsiniz. privateAlanlara sınıf düzeyinde erişime sahip olmak , böyle bir yöntemin, bu tür kamu yöntemlerini uygulamaya yönelik uyarılmış bir gereklilik olmadan uygulanmasını sağlar.
Malte Skoruppa

1
@MalteSkoruppa - Bu iyi bir örnek (yöntemi uygulamak equals).
Nicolas Barbulesco

@MalteSkoruppa - Ancak, yöntemin uygulanması equalsözel erişimciler çağırılarak yapılabilir.
Nicolas Barbulesco

@NicolasBarbulesco Evet, elbette, ancak önemli olan, ister özel erişimcileri kullanıyor olun, ister yöntemi uygulamak için özel alanlara doğrudan erişim sağlayın, privatesınıf düzeyinde erişim sağlamalıdır. Erişimcileri kullanmanın genellikle iyi bir alışkanlık olduğuna katılıyorum, ancak bu durumda çoğunlukla bir bağlam ve kişisel tarz meselesi. Etkili Java'da Joshua Bloch (madde 8) ve bu Dr. Dobbs makalesindeki Tal Cohen'in, nasıl uygulanacağını tartışırken kod listelerinde özel alanlara doğrudan eriştiğini unutmayın equals.
Malte Skoruppa

17

Bkz Java dil belirtimi, Bölüm 6.6.1. Erişilebilirliği Belirleme

Belirtir

Aksi takdirde, üye veya kurucu bildirilirse private, erişime ancak ve ancak üyenin veya kurucunun bildirimini içeren üst düzey sınıfın (§7.6) gövdesi içinde gerçekleşmesi durumunda izin verilir.

Daha fazla ayrıntı için yukarıdaki bağlantıya tıklayın. Yani cevap şu: Çünkü James Gosling ve Java'nın diğer yazarları bunun böyle olduğuna karar verdiler.


17

İyi soru. Nesne düzeyinde erişim değiştiricinin Kapsülleme ilkesini daha da zorlayacağı görülmektedir.

Ama aslında tam tersi. Bir örnek alalım. Bir yapıcıdaki bir nesneyi derinlemesine kopyalamak istediğinizi varsayalım, eğer o nesnenin özel üyelerine erişemiyorsanız. O zaman mümkün olan tek yol, tüm özel üyelere bazı genel erişimciler eklemektir. Bu, nesnelerinizi sistemin diğer tüm bölümlerine çıplak hale getirecektir .

Yani kapsülleme, dünyanın geri kalanına kapalı olmak anlamına gelmez. Kime açık olmak istediğin konusunda seçici olmak demektir.


2
Bu cevabın oylanması gerekiyor! Diğer cevaplar sadece 'kuralı' yeniden ifade eder, ancak yalnızca bu, kuralın arkasındaki nedeni gerçekten ortaya çıkarır ve noktaya gelir.
mzoz

4
Ama bir nesnenin kendisinin kopyalarını sağlamaktan sorumlu olması daha iyi olmaz mıydı? O halde, bir nesnenin derin bir kopyasına ihtiyacınız varsa, aynı sınıftan başka bir nesne veya farklı bir sınıftan bir nesne olmanız fark etmez: bu aynı mekanizma o.deepCopy()veya her neyse.
dirtside

4

Bu işe yarar çünkü içinde olduğunuz class Person- bir sınıfın kendi sınıf türünün içine girmesine izin verilir. Bu, bir kopya oluşturucu yazmak istediğinizde gerçekten yardımcı olur, örneğin:

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; }
};

Ya da yazma istiyorsanız operator+ve operator-bizim büyük sayı sınıf için.


Bu, bağımlılık enjeksiyonuna benzer bir şeydir. Özel değişkene erişemediğiniz başka bir sınıfın nesnesini de enjekte edebilirsiniz.
Nageswaran

Elbette, B sınıfı bir nesneden bir A sınıfı oluşturmaya çalışıyorsanız ve B'nin özel bileşeni varsa, o zaman ya A'nın bir arkadaş olarak ilan edilmesi gerekir veya yalnızca genel bölümleri görebilir [muhtemelen A, B'den türetilmişse korunur ].
Mats Petersson

Java ve .net'te arkadaş kavramı yoktur. Böyle durumlarda bununla nasıl başa çıkılır?
Nageswaran

1

Java'daki özel görünürlüğün anlambiliminin neden nesne seviyesinden ziyade sınıf seviyesinde olduğu sorusundaki 2 sent.

Rahatlığın burada anahtar rol oynadığını söyleyebilirim . Aslında, nesne düzeyinde bir özel görünürlük, OP tarafından gösterilen senaryoda yöntemleri diğer sınıflara (örneğin aynı pakette) maruz bırakmaya zorlayacaktır.

Gerçekte, sınıf-özel düzeyindeki görünürlüğün (Java'nın sunduğu gibi) nesne-özel düzeyindeki görünürlükle karşılaştırıldığında herhangi bir sorun yarattığını gösteren bir örnek bulamadım ve bulamadım.

Bununla birlikte, daha ince bir görünürlük politikaları sistemine sahip programlama dilleri, hem nesne düzeyinde hem de sınıf düzeyinde nesne görünürlüğü sağlayabilir.

Örneğin Eiffel , seçici dışa aktarma sunar: herhangi bir sınıf özelliğini, seçtiğiniz herhangi bir sınıfa, {NONE} (nesne-özel) 'den {ANY}' e (genel ile eşdeğeri ve ayrıca varsayılan), {PERSON} 'a aktarabilirsiniz. (sınıf-özel, OP'nin örneğine bakın), belirli sınıf gruplarına {KİŞİ, BANK}.

Ayrıca, Eiffel'de bir özelliği özel yapmanıza ve diğer sınıfların ona atamasını önlemek için bir alıcı yazmanıza gerek olmadığını belirtmek de ilginçtir. Eyfel'deki genel özniteliklere varsayılan olarak salt okunur modda erişilebilir, bu nedenle yalnızca değerlerini döndürmek için bir alıcıya ihtiyacınız yoktur.

Elbette bir özniteliği ayarlamak için bir ayarlayıcıya ihtiyacınız vardır, ancak öznitelik için "atayan" olarak tanımlayarak bunu gizleyebilirsiniz. Bu, dilerseniz ayarlayıcı çağrısı yerine daha uygun atama operatörünü kullanmanızı sağlar.


0

Çünkü private erişim değiştirici sadece içinde görünür hale sınıfın . Bu yöntem hala sınıfın içindedir .


Sorum şu, neden "sınıf içi" gibi tasarlandı ama neden "yalnızca nesne içinde" gibi değil?
Nageswaran

Çünkü java böyle yapılır.
darijan

Ve java neden böyle yaptı?
Nageswaran

Java başaramadı, Java yaratıcıları yaptı. Neden? Çünkü sallıyorlar!
darijan

1
Java yaratıcıları bunu herhangi bir sebep olmadan yapmayacaklar ve bunu yapmak için bir sebep olmalı;
Sebebini

0

privatealan alan ilan edildiği sınıf / nesne erişilebilir. İçinde bulunduğu sınıfın dışındaki diğer sınıflara / nesnelere özeldir.


-1

Burada anlamamız gereken ilk şey, yapmamız gereken tek şey oops ilkelerini takip etmektir, bu yüzden kapsülleme, veriyi paket (yani sınıf) içinde sarmalayıp tüm verileri Nesne olarak ve erişimi kolay olarak temsil eder. Bu yüzden alanı, tek tek erişildiğinden daha özel olmayan yaparsak. ve kötü paratice ile sonuçlanır.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.