Soru Java'da, paket özel, genel, korunan ve özel arasındaki fark


Java'da, her bir erişim değiştiricinin ne zaman kullanılacağı konusunda açık kurallar vardır, yani varsayılan (paket özel), public, protected ve privateyaparken class ve interface ve miras ile uğraşmak?


2500
2017-10-18 19:53


Menşei


private Paket içindeki diğer sınıflardan gizlenir. public Paket dışındaki sınıflara açılır. protected bir sürümüdür public sadece alt sınıflarla sınırlı. - Museful
@Tennenrishin - Hayır; Java’da C ++’ya karşı protected Yöntemi tüm paketten de erişilebilir kılar. Java'nın visiblity modelindeki bu aptallık, protected. - Nicolas Barbulesco
@Nicolas Bu paket, tüm paketlerden erişilebilir veya içermez protected. Erişim olarak niteleyici, hepsi protected paketin dışındaki alt sınıflara göstermektir. - Museful
@tennenrishin - peki, Nicolas'ın söylediği şey ... ve şimdi sadece tekrarlıyorsunuz. İlk söylediğin şey, protected - ve alıntı yapıyorum - 'sadece altsınıflar için kısıtlanmış bir versiyonudur.' kısıtlamak alt sınıflara erişim.) - luis.espinal
Ayrıca, Nicolas'taki korumalı erişim modunun aptalca olduğu konusunda da hemfikirim. Ne oldu, Java, yatay (kafes) ve dikey erişim kısıtlama niteleyicileri ile sınırlıydı. Varsayılan kapsam, paket olan kafes ile yatay / kafes kısıtlamasıdır. Kamu, kafesin tüm dünya olduğu başka bir yatay kısıtlamadır. Özel ve (C ++) korumalı dikey. Çapraz kesim erişimi olsaydık daha iyi olurdu, protected-packageAslında ihtiyacımız olan nadir durumlar için protected Korunan C ++ sürümüne eşdeğerdir. - luis.espinal


Cevaplar:


Resmi öğretici bazı kullanımları olabilir.

            │ Sınıf │ Paket │ Alt Sınıf │ Alt Sınıf │ Dünya
            │ │ │ (aynı pkg) │ (diff pkg) │
────────────┼───────┼─────────┼──────────┼──────── ──┼────────
kamu │ + │ + │ + │ + │ +
────────────┼───────┼─────────┼──────────┼──────── ──┼────────
korumalı │ + │ + │ + │ + │
────────────┼───────┼─────────┼──────────┼──────── ──┼────────
değiştirici yok │ + │ + │ + │ │
────────────┼───────┼─────────┼──────────┼──────── ──┼────────
özel │ + │ │ │ │

+: erişilebilir
boş: erişilebilir değil

4660
2017-10-18 19:57



Aynı sınıftaki korumalı bir yöntem veya örnek değişkenine, ancak .equals (Klass var) durumunda olduğu gibi olmayan bir nesneye erişmeye çalışıyorsanız bu çalışır mı? - Jordan Medlock
Alt sınıflar, üst sınıflarının aynı paketindeyse, alt sınıflarda varsayılan alanlar görünür. - Maksim Dmitriev
Java sürümleri ve JDK sürümleri 1.0.1'e kadar, özel bir yöntemle ve korumalı yöntemlerle veya değişkenlere yalnızca belirli bir sınıfın alt sınıflarına erişimi kısıtlayacak başka bir koruma formu oluşturmak için birlikte kullanabilirsiniz. - Vitalii Fedorenko
Bu, soruyu cevaplamayan bir cevap için çok oy ne zaman Her görünürlüğü kullanmalıyız (etkilerin ne olduğunu değil). - Bohemian♦
@Bohemian - Cevap, mümkün olduğunda en az izin veren erişim belirticisini kullanmanız gerektiğini (ya da bu tavsiyeyi de veren bağlantıyı izleyerek tam cevabı okuduğunuzu varsayar) sizi kabul eder. - iheanyi


(Caveat: Ben bir Java programcısı değilim, Perl programcısıyım. Perl'in, belki de sorunu neden bu kadar iyi anladığımı gösteren resmi bir koruması yok :))

Özel

Düşündüğün gibi, sadece sınıf içinde beyan edildiği şekilde görülebilir.

Paket Özel

Sadece tarafından görülebilir ve kullanılabilir paket içinde ilan edildi. Bu, Java'daki varsayılan değerdir (bazıları bir hata olarak görür).

korumalı

Özel Paket + alt sınıflar veya paket üyeler tarafından görülebilir.

halka açık

Herkes onu görebilir.

Yayınlanan

Kontrol dışı kodun dışında görünüyorum. (Java sözdizimi olmasa da, bu tartışma için önemlidir).

C ++ "arkadaş" adı verilen ek bir seviye tanımlar ve daha iyi bildiğinizi daha az bilirsiniz.

Ne zaman kullanmalısın? Bütün fikir bilgi saklamak için kapsülleme. Mümkün olduğunca kullanıcılarınızdan bir şeylerin nasıl yapıldığının ayrıntılarını gizlemek istersiniz. Niye ya? Çünkü sonra onları daha sonra değiştirebilirsin ve kimsenin kodunu kırmazsın. Bu, birilerinin sadece elden geçirdiğiniz kodu kullandığından endişe etmeden optimize etmenizi, yeniden düzenlemenizi, yeniden tasarlamanızı ve düzeltmenizi sağlar.

Yani, başparmak kuralı, sadece olması gerektiği gibi görünür hale getirmek. Özel olarak başla ve gerektiğinde daha fazla görünürlük ekle. Sadece, kullanıcının bilmesi için kesinlikle gerekli olanı, herkese açık hale getirdiğiniz her detayı, sistemi yeniden tasarlama becerinizi bozar.

Kullanıcıların davranışı kişiselleştirebilmeleri için, içerideki kişileri kamuya açık hale getirmek yerine, bunları geçersiz kılabiliyorlarsa, bu bağırsakları bir nesneye sokmak ve bu arayüzü herkese açık hale getirmek genellikle daha iyi bir fikirdir. Böylece yeni bir nesneyi kolayca bağlayabilirler. Örneğin, bir CD çalar yazıyor ve "bu CD hakkında bilgi bul" diyebiliyor olsaydınız, bu yöntemleri herkese açık hale getirmektense, tüm bu işlevselliği kendi nesnesine koyarsınız ve yalnızca nesne alıcısı / ayarlayıcınız olmasını sağlayın. . Bu sayede bağırsaklarınızı teşhir etme konusunda cimri olmak, iyi bir kompozisyon ve endişelerin ayrılmasını teşvik eder.

Şahsen, sadece "özel" ve "kamu" ile uğraşıyorum. Birçok OO dili sadece buna sahip. "Korumalı" kullanışlı olabilir, ama gerçekten bir hile. Bir arayüz özel durumdan çok olduğunda, kontrolünüz dışındadır ve kullanımları bulmak için başkalarının kodlarına bakmanız gerekir.

Burada "yayınlanmış" fikri geliyor. Bir arayüzün değiştirilmesi (yeniden kodlanması), onu kullanan tüm kodları bulmanızı ve bunu da değiştirmenizi gerektiriyor. Arayüz özel ise sorun olmaz. Korunuyorsa, tüm alt sınıflarınızı bulmanız gerekiyor. Halka açıksa, kodunuzu kullanan tüm kodu bulmanız gerekir. Bazen bu mümkündür, örneğin dahili kullanım için olan şirket kodu üzerinde çalışıyorsanız, yalnızca bir arabirimin herkese açık olması önemli değildir. Tüm kodu şirket havuzundan alabilirsiniz. Ama eğer bir arayüz "yayınlandı" ise, eğer kontrolünüzün dışında bir kod kullanılıyorsa, o zaman gözümün altında kalırsınız. Bu arayüzü veya risk kırma kodunu desteklemelisiniz. Korunmuş arayüzler bile yayınlanmış sayılabilir (bu yüzden korunmadığı için rahatsız etmemem).

Birçok dil, kamusal / korunan / özel olanın hiyerarşik doğasını, gerçekle uyumlu olmayan çok sınırlayıcı bulmaktadır. Bu amaçla bir kavram var. özellik sınıfıama bu başka bir gösteri.


358
2017-10-18 21:17



arkadaşlar -> "Bundan daha azını daha iyi biliyorsunuz" ---> Seçkin görünürlük sağlar, bu da paket gizliliğinden daha üstündür. C ++ 'da kullanımları vardır, çünkü tüm işlevler üye işlevleri değildir ve arkadaşlar herkesten daha iyidir. Tabi ki, kötü akılların kötüye kullanılması tehlikesi vardır. - Sebastian Mach
C ++ 'da "korunan" ın farklı bir anlamı olduğu da unutulmamalıdır - korunan bir yöntem etkili bir şekilde özeldir, fakat hala bir mirasçı sınıftan çağrılabilir. (Aynı paket içerisinde herhangi bir sınıf tarafından çağrılabildiği Java'nın aksine.) - Rhys van der Waerden
@RhysvanderWaerden C #, bu yönüyle C ++ ile aynıdır. Java'nın, alt sınıf için erişilebilir olan ancak paketin tamamında olmayan bir üyeyi bildirmesine izin vermemesi oldukça garip. Başım ağrıyor - paket bir çocuk sınıfından daha geniş bir kapsam! - Konrad Morawski
@KonradMorawski IMHO paketi, alt sınıftan daha küçük kapsamlıdır. Sınıfınızı nihai olarak bildirmediyseniz, kullanıcılar bunu alt sınıflara ayırmalıdır - böylece java korumalı, yayınlanan arayüzünüzün bir parçasıdır. OTOH, paketler tek bir kuruluş tarafından dolaylı olarak geliştirilir: ör. com.mycompany.mypackage. Eğer kodunuz paketimde kendini ilan ederse, örtülü olarak kendimi organizasyonumun bir parçası olarak ilan edersiniz, bu yüzden iletişim kurmalıyız. Bu nedenle, paket alt sınıftan (benim nesneyi genişleten kişiler) daha küçük / daha kolay ulaşan bir kitleye (şirketimdeki kişiler) yayınlar ve böylece daha düşük görünürlük olarak sayılır. - Eponymous
friend sınıflar arasındaki özel ilişkileri tanımlamak için iyidir. Doğru kullanıldığında birçok durumda üstün kapsülleme sağlar. Örneğin, dahili bağımlılıkları yapılandırılmış bir türe enjekte etmek için ayrıcalıklı bir fabrika sınıfı tarafından kullanılabilir. Kötü bir isme sahiptir çünkü iyi tasarlanmış bir nesne modelini doğru bir şekilde muhafaza etmeyen insanlar iş yüklerini hafifletmek için kötüye kullanabilirler. - Dennis


İşte tablonun daha iyi bir versiyonu. (Modüller için bir sütun ile gelecekteki kanıt.)

Java Access Modifiers

açıklamalar

  • bir özel üye bir tek bildirildiği gibi aynı sınıfta erişilebilir.

  • Bir üye ile erişim değiştirici yok Aynı paket içinde sadece sınıflar içinde erişilebilir.

  • bir korumalı üye aynı pakette tüm sınıflara erişilebilir ve diğer paketlerde alt sınıflar içinde.

  • bir halka açık üye tüm sınıflara erişilebilir (bir modül Bu paketin dışa aktarılmadığı beyan edilir).


Hangi değiştirici seçilir?

Erişim değiştiricileri, yanlışlıkla kırılmayı önlemeye yardımcı olan bir araçtır(*). Üyeyi sınıf, paket, sınıf hiyerarşisinde içsel olan veya hiç içsel olmayan bir şey olduğunu düşünüyorsanız ve buna göre erişim düzeyini seçip seçmediğinizi kendinize sorun.

Örnekler:

  • Bir alan long internalCounter Muhtemelen özel ve uygulama detayı olduğu için özel olmalı.
  • Yalnızca bir fabrika sınıfında (aynı pakette) başlatılması gereken bir sınıf, paketin sınırlı bir kurucusuna sahip olmalıdır, çünkü doğrudan paketin dışından çağrılması mümkün olmamalıdır.
  • Dahili void beforeRender() alt sınıflarda oluşturulmadan ve kanca olarak kullanılmadan hemen önce çağrılan yöntem korunmalıdır.
  • bir void saveGame(File dst) GUI kodundan çağrılan yöntem herkese açık olmalıdır.

(*) Kapsülleme tam olarak nedir?


245
2017-11-10 10:27





                | highest precedence <---------> lowest precedence
*———————————————+———————————————+———————————+———————————————+———————
 \ xCanBeSeenBy | this          | any class | this subclass | any
  \__________   | class         | in same   | in another    | class
             \  | nonsubbed     | package   | package       |    
Modifier of x \ |               |           |               |       
————————————————*———————————————+———————————+———————————————+———————
public          |              |          |              |      
————————————————+———————————————+———————————+———————————————+———————
protected       |              |          |              |   ✘   
————————————————+———————————————+———————————+———————————————+———————
package-private |               |           |               |
(no modifier)   |              |          |       ✘       |   ✘   
————————————————+———————————————+———————————+———————————————+———————
private         |              |     ✘     |       ✘       |   ✘    

165
2018-01-09 21:42



Sözcüklere koymaya değer - "Korumalı değiştirici nesneyi diğer paketlerde kullanılabilir hale getirirken, varsayılan / değiştirici aynı pakete erişimi kısıtlıyor" - vanguard69
@ vanguard69, protected değiştirici işaretli hale getirir şey (diğer bir sınıfta başka bir sınıf için kullanılabilir) (sınıf, yöntem veya alan) sadece iff Diğer sınıf, sınıfın bir alt sınıfıdır. protected- işaretlenmiş şey beyan edildi. - Abdull
"Nonsubbed"? "bu alt sınıf başka bir pakette"? Huh. Java'yı bildiğimi sanıyordum. - sehe
@AlexanderFarber belirli bir tarayıcı yapılandırması için optimize ettiniz mi? Bu benim kromum şimdi Ve bu Firefox - sehe
Hmm hadi değişime dönelim o zaman - Alexander Farber


Kolay kural. Her şeyi özel ilan ederek başlayın. Ve sonra ihtiyaçlar ortaya çıktıkça ve kamuoyuna doğru ilerledikçe, bunu ilerletir.

Üyeleri açığa vurduğunuzda, temsil seçimlerini veya soyutlama seçimlerini gösterip göstermediğinizi kendinize sorun. Birincisi, gözlemlenebilir davranışından ziyade gerçek temsile çok fazla bağımlılık getireceğinden kaçınmak istediğiniz bir şeydir.

Genel bir kural olarak, alt sınıflara göre yöntem uygulamalarını geçersiz kılmaya çalışmaktan kaçınmaya çalışıyorum; mantığı bozmak çok kolay. Geçersiz kılmayı düşündüğünüzde soyut korunan yöntemleri bildirin.

Ayrıca, refactor'unuzda bir şeyler kırılmasını önlemek için geçersiz kılındığında @Override ek açıklama kullanın.


131
2017-10-18 20:00



@RuchirBaronia, "dünya" = nerede olursa olsun uygulamadaki tüm kod. - Andrejs


Aslında basit bir ızgara gösterisinden biraz daha karmaşıktır. Kılavuz, bir erişime izin verilip verilmediğini size söyler, ancak tam olarak bir erişim nedir? Ayrıca, erişim seviyeleri karmaşık yollarla iç içe geçmiş sınıflar ve kalıtım ile etkileşime girer.

"Varsayılan" erişim (bir anahtar kelimenin yokluğuyla belirtilir) de denir paket-özel. İstisna: Bir arayüzde, hiçbir değiştirici kamu erişimi anlamına gelir; halka dışındaki değiştiriciler yasaktır. Enum sabitleri her zaman açık.

özet

Bu erişim belirticisine sahip bir üyeye erişim izni var mı?

  • Üye private: Sadece üye, arama koduyla aynı sınıfta tanımlanmışsa.
  • Üye özel pakettir: Sadece çağıran kod paketin hemen kapağındaki üyenin üyesiyse.
  • Üye protected: Aynı paket veya üye, arama kodunu içeren sınıfın bir üst sınıfında tanımlanmışsa.
  • Üye public: Evet.

Hangi erişim belirleyicileri geçerli

Yerel değişkenler ve resmi parametreler erişim belirleyicilerini alamaz. Kapsam belirleme kurallarına göre dışarıdan içsel olarak erişilemedikleri için, bunlar etkili bir şekilde özeldir.

En üstteki sınıflar için, sadece public ve paket-özel izin verilir. Bu tasarım seçimi muhtemelen protected ve private Paket seviyesinde fazlalık olacaktır (paketlerin kalıtımı yoktur).

Tüm üyeler, sınıf üyelerinde (yapıcılar, yöntemler ve statik üye işlevleri, yuvalanmış sınıflar) mümkündür.

İlgili: Java Sınıfı Erişilebilirlik

Sipariş

Erişim belirleyicileri kesinlikle sipariş edilebilir

genel> korumalı> paket-özel> özel

anlamında public en çok erişim sağlar private en az. Özel bir üye üzerinde mümkün olan herhangi bir referans, paket özel bir üye için de geçerlidir; Paket özel üyeye yapılan başvurular korunan bir üye için geçerlidir, vb. (Korunan üyelere aynı paketteki diğer sınıflara erişim verilmesi bir hata olarak kabul edildi.)

notlar

  • Bir sınıfın yöntemleri Hangi Aynı sınıfa ait diğer nesnelerin özel üyelerine erişmesine izin verilir. Daha doğrusu, C sınıfı bir yöntem C'nin herhangi bir alt sınıfındaki nesnelerin C üyelerine erişebilir. Java, yalnızca sınıf tarafından örneğin erişimi kısıtlamayı desteklemez. (Bunu kullanarak destekleyen Scala ile karşılaştırın private[this].)
  • Bir nesne oluşturmak için bir kurucuya erişmeniz gerekir. Bu nedenle, eğer tüm kurucular özelse, sınıf sadece sınıf içinde yaşayan kodlar tarafından oluşturulabilir (tipik olarak statik fabrika yöntemleri veya statik değişken başlatıcılar). Benzer şekilde paket özel veya korumalı inşaatçılar için.
    • Sadece özel kuruculara sahip olmak, sınıfın harici olarak alt sınıflara eklenemeyeceği anlamına gelir, çünkü Java bir alt sınıfın yapıcılarını örtülü veya açık bir şekilde bir üst sınıf kurucusunu çağırmak ister. (Ancak, bunu alt sınıflara ayıran iç içe geçmiş bir sınıf içerebilir.)

İç sınıflar

Ayrıca düşünmelisin İç içe iç sınıflar gibi kapsamlar. Karmaşıklığın bir örneği, iç sınıfların, kendilerinin erişim düzenleyicilerini alabilecekleri üyelere sahip olmasıdır. Bu yüzden kamuya açık bir üye ile özel bir iç sınıfa sahip olabilirsiniz; üye erişilebilir mi? (Aşağıya bakınız.) Genel kural, kapsamlara bakmak ve her bir seviyeye erişip erişemeyeceğinizi anlamak için tekrar tekrar düşünmektir.

Ancak, bu oldukça karmaşık ve tüm ayrıntılar için Java Dil Özelliğine bakın. (Evet, geçmişte derleyici hataları olmuştur.)

Bunların nasıl etkileştiğini görmek için bu örneği düşünün. Özel iç sınıfları “sızdırmak” mümkündür; Bu genellikle bir uyarıdır:

class Test {
    public static void main(final String ... args) {
        System.out.println(Example.leakPrivateClass()); // OK
        Example.leakPrivateClass().secretMethod(); // error
    }
}

class Example {
    private static class NestedClass {
        public void secretMethod() {
            System.out.println("Hello");
        }
    }
    public static NestedClass leakPrivateClass() {
        return new NestedClass();
    }
}

Derleyici çıkışı:

Test.java:4: secretMethod() in Example.NestedClass is defined in an inaccessible class or interface
        Example.leakPrivateClass().secretMethod(); // error
                                  ^
1 error

Bazı ilgili sorular:


94
2017-09-13 07:38





Kural olarak:

  • özel: sınıf kapsamı.
  • varsayılan (veya paket-özel): paket kapsamı.
  • korumalıpaket kapsamı + çocuk (paket gibi, ancak farklı paketlerden alt sınıflara ayırabiliriz). Korumalı değiştirici her zaman "ebeveyn-çocuk" ilişkisini korur.
  • halka açık: her yerde.

Sonuç olarak, erişim hakkını üç haklara bölersek:

  • (D) irect (aynı sınıf içindeki bir yöntemden yararlanın).
  • (Referans (sınıfa bir referans kullanarak veya "nokta" sözdizimi kullanarak bir yöntemi çağırın).
  • (I) 'nheritance (alt sınıflandırma yoluyla).

sonra bu basit tabloya sahibiz:

+—-———————————————+————————————+———————————+
|                 |    Same    | Different |
|                 |   Package  | Packages  |
+—————————————————+————————————+———————————+
| private         |   D        |           |
+—————————————————+————————————+———————————+
| package-private |            |           |
| (no modifier)   |   D R I    |           |
+—————————————————+————————————+———————————+
| protected       |   D R I    |       I   |
+—————————————————+————————————+———————————+
| public          |   D R I    |    R  I   |
+—————————————————+————————————+———————————+

63
2017-12-18 18:01