Neden bir sınıfı şu şekilde tanımlayamıyoruz? protected
?
Yapamayacağımızı biliyorum ama neden? Belirli bir nedeni olmalı.
Neden bir sınıfı şu şekilde tanımlayamıyoruz? protected
?
Yapamayacağımızı biliyorum ama neden? Belirli bir nedeni olmalı.
Yanıtlar:
Çünkü hiç mantıklı değil.
Korumalı sınıf üyesi (yöntem veya değişken), aynı pakete özel (varsayılan görünürlük) gibidir, ancak alt sınıflardan da erişilebilir.
Java'da 'alt paket' veya 'paket mirası' diye bir kavram olmadığından, korumalı sınıf veya paket-özel olarak bildirmek aynı şey olacaktır.
Bununla birlikte, yuvalanmış ve iç sınıfları korumalı veya özel olarak bildirebilirsiniz.
open
mevcut paketin dışında alt sınıflamaya izin veren Kotlin'de ( protected
Java'da ters varsayılanla bunu engellediğini hayal edebilirsiniz ).
Bildiğiniz gibi, varsayılan paket seviyesi erişim içindir ve korumalı, paket seviyesi artı paket dışı sınıflar içindir, ancak bu sınıfı genişletir (Burada dikkat edilmesi gereken nokta, sınıfı yalnızca görünürse genişletebilirsiniz!). Şöyle koyalım:
Bu sınıfın yalnızca birkaç sınıf tarafından alt sınıflara ayrılmasını kısıtlamanın bir yolu olmadığından (sınıfın, bir paketteki / bir paketin dışındaki tüm kullanılabilir sınıflardan yalnızca birkaç sınıf tarafından miras alınmasını kısıtlayamayız), korumalı erişim belirteçlerinin kullanımı yoktur üst düzey sınıflar için. Dolayısıyla buna izin verilmez.
public class A
{
protected class B
{
}
}
@Nikita Rybak cevabının iyi noktaları var ama detay eksikliği, kendimi derinlemesine düşünmeden fikri basitçe anlayamıyorum , aşağıdaki düşündüğüm şey ve şimdi sebebini tamamen anlamalıyım.
Dört erişim değiştirici, 1. seviyenin genel ve 4. seviyenin özel olduğunu varsayın (bu tabloya göre sırayla ). Bilmemiz gereken ilk şey, sınıfın neden üst düzeyde özel olarak tanımlanamayacağıdır.
Öyleyse "özel sınıf foo" (tanımlanmış bir özel üye, yani sınıfın kendisi bir üyedir) izin veriyorsa, dış (üyeyi içeren) nedir? Dosya kapsamı? Hayır, dıştaki dosya anlamsızdır çünkü tek bir dosyadaki birden çok sınıf bile ayrı sınıf dosyalarında derlenecektir. Yani dış kısım pakettir . Ancak 3. düzey varsayılan erişim değiştiricisi zaten "özel paket" anlamına gelir . Dolayısıyla, 4. seviye özel erişim değiştiricisi kullanılmayacak / kullanılmayacaktır.
Ancak iç içe geçmiş özel sınıfa izin verilir, çünkü doğrudan dış sınıf paket değildir, örneğin :
class PrivateNestedMain {
private static class Inner {
public static void main(String[] args) {
System.out.println("Hello from Inner!");
}
}
}
Şimdi ya "korumalı sınıf foo" izin verirse? korumalı ana özellik alt sınıftır, bu nedenle dış (kapsama göre, ancak yine de isteğe bağlıdır) alt sınıfın stilini sağlamalıdır , yani alt paket, veya package A extends package B
, ancak böyle bir şey bilmiyoruz. Bu nedenle, korumalı, dışın paket olduğu (yani böyle bir alt paket olmadığı) üst düzeydeki tam potansiyeli (ana kapsam alt sınıf genişliğindedir) kullanamaz, ancak korumalı, dışın sınıf olduğu iç içe sınıfta tam potansiyeli kullanabilir ( yani alt sınıf olabilir) :
class ProtectedNestedMain {
protected static class Inner {
public static void main(String[] args) {
System.out.println("Hello from Inner!");
}
}
}
Yukarıda belirtilen "tam potansiyeli kullanamıyorum" çünkü alt sınıf genişliğine erişemiyor çünkü dış alt sınıf yok, bu aslında korumaya izin verilebileceği anlamına geliyor , bu sadece paketin işini tekrarlamaktan kaçınmak için bir seçim meselesi. -dış, alt sınıflara uygun değilse özel , aşağıya bakın.
Kafam karıştı : https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html adresindeki ünlü tablodan kaynaklanıyor :
1. seviye (genel) ve 3. seviye (paket-özel) izin veriyorsa, nasıl olur da 2. seviye (korumalı) arasına izin verilmez?
kamu desteği alt sınıfı çok kolay yanıltıcı. Bu tabloyu okumanın doğru yolu
dışta alt sınıf özelliği varsa public support alt sınıfı.
Aynı yanıltıcı durum özel paket için de geçerlidir, özel paket alt sınıfı ( hücrede N ) desteklemez , dışta alt sınıf kavramının geçerli olduğu anlamına gelmez.
Bu , dış sınıfta alt sınıf özelliği yoksa Alt Sınıf sütununu yok saymamız gerektiği anlamına gelir :
Şimdi görebileceğimiz gibi, hem korumalı hem de özel paket şimdi aynı seviyededir ( YYN ), neden ara seviyeye izin verilmediğine dair kafa karışıklığı yok. Genel olarak, Java, kafa karıştırmayı önlemek için yalnızca paket-özel aşırı korumalı seçer ( bu yalnızca bir seçim meselesidir , ancak korumalı ana özellik alt sınıftır, bu nedenle özel paket üstündür) ve sonuç , üst düzeyde yalnızca 2 erişim değiştiriciye izin verilir:
En üst düzeyde - genel veya özel paket (açık değiştirici yok).
Korumalı bir alanın tanımlanması, bu alanı yalnızca miras yoluyla paketin içinde olduğu kadar paketin dışında da erişilebilir kılar (Yalnızca alt sınıfın içinde).
Yani bir sınıfı korumalı yapmamıza izin verilirse, o zaman paketin içinde ona çok kolay bir şekilde erişebiliriz, ancak bu sınıfa paketin dışında erişmek için önce bu sınıfın tanımlandığı, paketi olan varlığı genişletmemiz gerekir.
Ve bir paket genişletilemediğinden (içe aktarılabildiğinden), korumalı bir sınıfın tanımlanması onu yine package-private yapar ki bu, onu zaten yapabildiğimiz gibi varsayılan olarak tanımlamaya benzer. Bu nedenle, özel bir sınıfı tanımlamanın hiçbir faydası yoktur, sadece işleri belirsiz hale getirir.
Daha fazla bilgi için Neden bir dış Java sınıfı özel veya korumalı olamaz konusunu okuyun
Korumalı halka benzemez. Korumalı, hem paket düzeyinde erişime sahiptir, hem de yalnızca kalıtım yoluyla paketlerin dışından erişilebilir ... Bir sınıf, bir paketin dışında A diyorsa, başka bir paketten bir sınıf INHERITS (INHERITANCE kullanılarak korunan yöntemle) bu B sınıfının yöntemlerine erişebilir. korumalı yöntemlere sahiptir, ancak bu sınıftan türetilen alt sınıflar, yani A korumalı yöntemlere erişemez ... bunun tersi genel olarak olur ..
Misal:
package 2;
class B
{
protected void method1()
{
}
}
package 1;
import 2.B;
class A extends B
{
//can access protected method
}
class C extends A
{
//can't access the protected method
}
"korumalı" davranışı = "varsayılan" davranışı + "herhangi bir paketteki herhangi bir alt sınıfta kullan".
Her neyse, sınıf için varsayılan erişim değiştiricimiz var, korumalı erişim değiştiriciden elde edebileceğimiz tek avantaj şudur: - alt sınıflandırma yoluyla herhangi bir pakette kullanmak. Ancak alt sınıf için, "korumalı" üst sınıfın görünürlüğü özel olacaktır. Yani erişilemez. Temel olarak, korumalı bir üst düzey sınıfınız varsa, hiçbir dış sınıf, onu alt sınıflara ayırarak erişim sağlayamaz. Üst düzey bir sınıf için bu nedenle korunmak anlamsızdır.
Korumalı : Yalnızca paket düzeyinde GÖRÜNÜR *.
sınıf korumalı olarak tanımlanmıştır ---> genişletilemez dış paketten (görünmez).
Ve eğer genişletilemezse, onu korumalı olarak tutmak anlamsızdır , çünkü o zaman varsayılan olacaktır. izin verilen erişim .
Aynısı özel tanımlı sınıflar için de geçerlidir .
Not: İç içe veya iç sınıflar korumalı veya özel olarak tanımlanabilir .
* : Korumalı anahtar kelimeyi keşfedin , bu cevabı kısa ve öz yaptım.
@ Akash5288'den gelen cevap bana mantıklı gelmedi:
Tüm sınıfların alt sınıfa girmesine izin verilirse, bu genel erişim tanımlayıcısına benzer olacaktır.
Bu sınıfın yalnızca birkaç sınıf tarafından alt sınıflara ayrılmasını kısıtlamanın bir yolu olmadığından (sınıfın, bir paketteki / bir paketin dışındaki tüm kullanılabilir sınıflardan yalnızca birkaç sınıf tarafından miras alınmasını kısıtlayamayız), korumalı erişim belirteçlerinin kullanımı yoktur üst düzey sınıflar için. Dolayısıyla buna izin verilmez.
Daha sonra aynı mantığı korumalı yöntemlere ve değişkenlere de uygulayabilirsiniz, bunlar da "herkese benzer" olur. Bir paketin dışındaki tüm sınıflar genel sınıfımızı genişletebilir ve korumalı yöntemlerini kullanabilir. Yöntemleri ve değişkenleri genişletilmiş sınıflarla kısıtlamak neden uygun, ancak tüm sınıfı kısıtlamak uygun değil? "Herkese benzer", "genel" ile aynı değildir. Benim yorumum, korumalı yöntemlere izin vermenin iyi olduğu için korumalı bir sınıfa izin vermenin tamamen iyi olduğu yönündedir.
"Erişemediğiniz / göremediğiniz bir sınıfı genişletemezsiniz" yanıtı daha mantıklıdır.
Bu soruya mantıklı gelen şey, JVM'nin C (Sun JVM) ve C ++ (oracle JVM) ile yazılmış olmasıdır, bu nedenle derleme sırasında java dosyamızdan .class dosyaları oluşturacağız ve eğer Korumalı anahtar kelimeli bir sınıf bildirirsek daha sonra JVM tarafından erişilemez.
Korunan sınıfa JVM tarafından erişilemeyeceğinin yanıtı, korumalı alanlara aynı paket içinde veya yalnızca kalıtım yoluyla farklı paketlere erişilebildiğinden ve JVM'nin miras alacak şekilde yazılmadığı için JVM tarafından erişilmeyeceğidir. Umarım bu, bu soruyu karşılar :)
Benzer şekilde, üst düzey bir sınıf özel olamaz. Aşağıdaki gibi açıklama:
Öyleyse, özel bir sınıf tanımlayacak olursak, bu sınıfa yalnızca, bizim durumumuzda paketi olan içinde tanımlandığı varlık içinde erişilebilir olacaktır?
Bu nedenle, sınıfa özel erişimin tanımlanması, varsayılan anahtar kelimenin bizim için zaten yaptığı aynı paket içinde erişilebilir olmasını sağlayacaktır, Bu nedenle, özel bir sınıf tanımlamanın hiçbir faydası yoktur, bu sadece işleri belirsiz hale getirir.
korumalı, üyeye aynı paketteki herhangi bir sınıf ve başka bir paket içinde olsalar bile alt sınıflar tarafından erişilebileceği anlamına gelir.
Misal:
package a;
class parent{
protected void p();
}
package b;
import a.p;
class child extends parent{
//you can access method which is protected in the parent in the child
}
class another extends child {
//here you can not access the protected method
}
bir dış sınıf korumalı tarafından bildirilmişse, sınıfa sadece aynı paket ve alt sınıfından ancak farklı paketlerden erişilebilmesini istediğinizi düşünüyorum. Bununla birlikte, korumalı bir sınıf için alt sınıflar oluşturmak mümkün değildir, çünkü "Köpek Sınıfı Hayvan'ı genişletir" yazdığınızda, korumalı "Hayvan" nedeniyle yalnızca alt sınıfı tarafından erişilebilir, açıkçası "Köpek", "Hayvan" alt sınıfı değildir .
Yani korumalı dış sınıf, (varsayılan) dış sınıfla aynıdır!