Özel bir üyeye neden statik bir yöntemle erişilebilir?


25

Aşağıdaki sahte kodu, Java ve PHP denedim ve her ikisi de çalıştı:

class Test { 

    private int a = 5;

    public static function do_test(){
        var t = new Test();
        t.a = 1;
        print t.a // 1
    }

}

Test::do_test();

Bunu neden OOP paradigmasında yapabilirsiniz ve bunun kullanımı nedir?


6
Neden olmasın? Java'da özel üyeler özel değil, kaynak dosyaya özeldir . Akla gelen ilk kullanım equals, başka bir vakanın özel alanlarını kontrol etmek zorunda olmasıdır. (Bu kısa olduğu için yorum olarak yayınlanıyor ve bu yaklaşımın OOP-si hakkında hiçbir şey yok)
Ordous

2
Statik metotların sahip olmadığına dikkat edin this, bu yüzden kendi sınıflarının alabileceği tek nesneler kendi oluşturdukları nesnelerdir (veya bir parametre olarak iletilir). Dolayısıyla, bunun bir kapsülleme veya güvenlik deliği ihlali olduğunu düşünüyorsanız, çok büyük bir şey değil ve takılmaya değmeyebilir.
Kilian Foth

4
Bunun neden aşağılandığından emin değilim. Soru önemsiz olabilir (ish), ancak OP sormadan önce davranışı iki dilde test etme zorluğunu yaşadı. Bu genellikle yeni gelenlerden gördüğümüzden çok daha fazla çaba.
yannis

1
@YannisRizos Kabul etti ve aslında sorunun önemsiz olduğunu düşünmüyorum. "En az ayrıcalık ilkesini" takip etmenin sonuçları vardır. Bu, bir örneğin içindekilerine erişmesi gerekmeyen yardımcı işlevlerin ayrı bir sınıfta tanımlanması gerektiği anlamına gelir ve bunun tersine bu kural izlendiğinde, aynı sınıf içinde statik bir yöntem olduğunda, iç duruma erişdiğini bilirsiniz.
Doval,

1
Aslında, meslektaşlarıma sorduğumda hepsi de bunun imkansız olduğunu söyledi. Bu yüzden önemsiz olmadığını düşündüm
Ben

Yanıtlar:


17

Java'da özel değişkenler tüm sınıfa görünür. Statik yöntemlerden ve aynı sınıfın diğer örneklerinden erişilebilirler.

Bu, örneğin fabrika yöntemlerinde kullanışlıdır . Bir fabrika yöntemi genellikle bunları uygulama koduna bırakmak istemediğiniz kadar karmaşık olan bir nesneye ilklendirmeleri yapar. İlklendirmeyi yapmak için, fabrika yönteminin genellikle göstermek istemediğiniz sınıflara erişim sağlaması gerekir. Özel değişkenlere doğrudan erişebilmek hayatınızı çok kolaylaştırıyor.

Bununla birlikte, bir sınıfın uygulama ayrıntılarını statik yöntemlerden veya o sınıfın diğer örneklerinden bile gizlemek istediğinizde, özel sınıf veri modelini takip edebilirsiniz . Bir sınıfın tüm özel değişkenlerini özel bir iç sınıfa yerleştirin ve alıcıları veya ayarlayıcıları o iç sınıfın alıcılarına ve ayarlayıcılarına devredin.

Başka bir seçenek de, sınıfın tüm genel yöntemlerini ilan eden sınıf için bir arayüz tanımlamak ve sonra sadece mümkün olduğunda bu arayüzün altındaki sınıfa başvuru yapmaktır. Arabirim türüne yapılan bir referans, arabirimde bildirilmeyen hiçbir şeye erişmek için kullanılamaz, nerede olursa olsun (yansıma hariç). Arayüzünüz olmayan (örneğin C ++ gibi) nesne yönelimli bir programlama dili kullandığınızda, bunlar gerçek sınıf tarafından miras alınan soyut bir temel sınıfla simüle edilebilir.

interface ITest {
     public int getA();
}

class Test implements ITest { 

    private int a = 5;

    public int getA() { return a; } // implementation of method declared in interface

    public static void main(){
        ITest t = new Test();
        t.a = 1; // syntax error: Interface ITest has no "a"
        System.out.println(t.getA()); // calls Test.getA, visible because ITest declares it
    }

}

Özel sınıf veri modelinin faydalı olduğu bir durum düşünebiliyor musunuz? Kişisel olarak yalnızca GUI kurulumlarında (Swing, vb.) Ya da kodlama alıştırmalarında statik iç sınıfları kullanıyorum, çünkü bir egzersizi birden fazla kaynak dosyaya yaymak istemiyorum.
InformedA

1
Bir sınıfın iç üyelerini diğer örneklerden gizlemek , karşılığında herhangi bir şey elde etmeden, sınıfların arabirimler üzerindeki avantajlarından birini ortadan kaldırır. Daha basit ve daha esnek bir çözüm sadece bir arayüz kullanmaktır.
Doval,

3

Bazı diller ve çalışma zamanı çerçeveleri (örneğin, Java, .NET), belirli bir sınıf için kodu derleyen herhangi birinin, bu sınıfın herhangi bir özel üyesini, haklarına zarar verecek şekilde kullanmamaya güvenebileceğini varsaymaktadır. operasyon. Diğer diller ve çerçeveler bu konuda daha kısıtlayıcı olan ve çalışan kod tarafından haricinde bir örneğinin özel üyelerine erişim izin vermez o örneğinde . Her iki tasarımın da avantajları ve dezavantajları vardır.

Bir sınıf içindeki herhangi bir kodun herhangi bir vakanın özel üyelerine erişmesine izin vermenin en büyük avantajı, bu erişim düzeyinin uygun olduğu durumlar olması ve privatebu şekilde çalışmanın bu amaç için farklı bir erişim niteleyicisine sahip olma ihtiyacını ortadan kaldırması veya Aksi takdirde, kodları üyelerin aksi takdirde ideal olandan daha geniş bir şekilde ortaya çıkarması için zorlarlar.

Bu tür erişime izin vermemenin bir avantajı (Microsoft Ortak Nesne Modeli'nde (COM) olduğu gibi) dış kodun sınıfları arabirim olarak ele almasına izin vermesidir. Bir sınıf ImmutableMatrixözel veya korumalı bir double[][]yedekleme alanı içeriyorsa ve sınıf içindeki kod diğer örneklerin yedekleme dizisini incelerse, harici kodun kullanabileceği bir dizi dizisi içermeyen sınıf (ör ZeroMatrix. IdentityMatrix) Tanımlamak mümkün olmaz bir Immutable2dMatrix, bu sınıfı destekleme alanını dahil etmek zorunda kalmadan. Eğer içindeki hiçbir şey , Immutable2dMatrixbaşka herhangi bir örneğin özel üyelerini kullanmazsa this, sınıfı yeniden adlandırmak ve yukarıda belirtilen dizili olmayan sınıfları ve alt türler olarak sahip olabilecek ImmutableArrayBackedMatrixyeni bir soyut ImmutableMatrixsınıfı tanımlamak mümkün olacaktır ImmutableArrayBackedMatrix.

Bu tür yeniden düzenleme işlemlerinin , dilin bu yetenekten yararlanmadığı ve gerçekte dış örnekleri incelemediği durumlar dışında ImmutableMatrix, destek dizisini incelemesi için "izin ver" seçeneğinin olması dışında engellenmeyeceğini unutmayın this. Bir dilin olmasının birincil etkisi, bu tür bir kullanımı sınırlandırması, derleyicinin derhal bu tür yeniden düzenleme işlemlerine uygun olmayacak herhangi bir kod yazma girişiminde sıkışık hale getirmesidir.


2

Java kesinlikle nesne yönelimli bir dil değil, sınıf temelli bir dildir - sınıf, örnek yerine işlem ve davranış erişimini belirler.

Bu yüzden, kesinlikle nesne yönelimli olmayan şeyler yapmanıza izin verdiği için çok şaşırmayın.

Yöntem, örnekle aynı sınıf kapsamında olduğundan, özel üyelere tam erişime sahiptir. Benzer kurallar, dış sınıf örneklerinden verilere erişen iç sınıf örneklerini de yönetir - bir iç sınıf örneği, dış sınıfın özel üyelerine erişebilir.

Bu, kopya oluşturma ve taşıma yapıcıları için yararlı olduğu C ++ 'dan devralınır. Ayrıca, değerlerinin kamuya açık bir şekilde erişilemeyen üyelere bağlı olduğu iki nesneyi karşılaştırmak veya birleştirmek için kullanışlıdır (örneğin, Java'daki bir dizinin alıcısı diziyi kopyalamalıdır, böylece istemci kodu değiştirilemez, nesnenin iç durumu, ancak nesne eşitliğini karşılaştırmak için dizileri kopyalamak zorunda kalmak verimli değildir)

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.