Protected修飾子とpackage private修飾子の違いに関するさまざまな記事を見てきました。これら2つの投稿の間に矛盾があることがわかりました
「パッケージプライベート」メンバーアクセスは、デフォルト(修飾子なし)アクセスと同義ではありませんか?
これで受け入れられた答えは言う
Protected修飾子は、メンバーが(package-privateのように)自分のパッケージ内でのみアクセスでき、さらに、別のパッケージのクラスのサブクラスからもアクセスできることを指定します。
これで受け入れられた答えは言う
保護レベルのアクセスを満たすには、次の2つの条件を満たしている必要があります。
- クラスは同じパッケージ内にある必要があります。
- 継承関係が必要です。
彼らは矛盾していませんか?他の記事の私の理解から、最初の投稿は、protected == package-private + subclass in other packageという正しい答えを与えます。
このステートメントが正しい場合、17行目のサブクラスCatで次のエラーメッセージが表示されてこのコードが失敗する理由
The method testInstanceMethod() from the type Animal is not visible
スーパークラスとサブクラスのコードは次のとおりです。
package inheritance;
public class Animal {
public static void testClassMethod() {
System.out.println("The class" + " method in Animal.");
}
protected void testInstanceMethod() {
System.out.println("The instance " + " method in Animal.");
}
}
package testpackage;
import inheritance.Animal;
public class Cat extends Animal{
public static void testClassMethod() {
System.out.println("The class method" + " in Cat.");
}
public void testInstanceMethod() {
System.out.println("The instance method" + " in Cat.");
}
public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
myAnimal.testClassMethod();
myAnimal.testInstanceMethod();
}
}
上記のコードが失敗する理由を明確にしてください。それは非常に便利です。ありがとう
最初の答えは基本的に正しいです-protected
メンバーは次の方法でアクセスできます
ただし、ちょっとしたトリックがあります。
6.6.2保護されたアクセスの詳細
オブジェクトの保護されたメンバーまたはコンストラクターは、そのオブジェクトの実装を担当するコードによってのみ宣言されているパッケージの外部からアクセスできます。
つまり、他のパッケージのサブクラスは、スーパークラスの任意のインスタンスのprotected
メンバーにアクセスできず、独自の型のインスタンスでのみアクセスできます(typeはコンパイル時の式です。時間チェック)。
例(このコードがCat
にあると仮定):
Dog dog = new Dog();
Animal cat = new Cat();
dog.testInstanceMethod(); // Not allowed, because Cat should not be able to access protected members of Dog
cat.testInstanceMethod(); // Not allowed, because compiler doesn't know that runtime type of cat is Cat
((Cat) cat).testInstanceMethod(); // Allowed
protected
によってDog
のCat
メンバーにアクセスすると、Dog
の不変式が壊れる可能性がありますが、Cat
は独自のprotected
にアクセスできるため、メンバーは、自身の不変式を保証する方法を知っているため、安全に。
詳細なルール:
6.6.2.1保護されたメンバーへのアクセス
保護されたメンバーmが宣言されているクラスをCとします。アクセスはCのサブクラスSの本体内でのみ許可されます。さらに、Idがインスタンスフィールドまたはインスタンスメソッドを示す場合、次のようになります。
- QがExpressionNameである修飾名Q.Idによるアクセスの場合、式QのタイプがSまたはSのサブクラスである場合にのみアクセスが許可されます。
- Eがプライマリ式であるフィールドアクセス式E.Idによるアクセス、またはEがプライマリ式であるメソッド呼び出し式E.Id(。。。)によるアクセスの場合、アクセスは次の場合にのみ許可されます。 EのタイプがSまたはSのサブクラスである場合.
6.6.2.2保護されたコンストラクタへの限定アクセス
Cをプロテクトコンストラクターが宣言されているクラスとし、Sをプロテクトコンストラクターの使用が宣言されている最も内側のクラスとします。次に:
- アクセスがスーパークラスコンストラクター呼び出しsuper(。。。)またはE.super(。。。)の形式の修飾スーパークラスコンストラクター呼び出し(Eはプライマリ式)である場合、アクセスは許可されます。
- アクセスがフォームnew C(。。。){...}の匿名クラスインスタンス作成式、またはフォームE.new C(。。))...の修飾クラスインスタンス作成式による場合}、ここでEはプライマリ式であり、アクセスは許可されます。
- それ以外の場合、アクセスがフォームnew C(。。。)の単純なクラスインスタンス作成式、またはフォームE.new C(。。。)の修飾されたクラスインスタンス作成式による場合(Eはプライマリ式) 、アクセスは許可されていません。保護されたコンストラクターは、それが定義されているパッケージ内からのみ、クラスインスタンス作成式(匿名クラスを宣言しない)によってアクセスできます。
以下も参照してください:
保護されたアクセスでは、メンバーは同じパッケージでアクセスされ、継承されたクラスメンバーの別のパッケージでもアクセスできます。
パッケージアクセスでは、同じパッケージ内のクラスのメンバーにアクセスできます。他のパッケージのクラスメンバーは、パッケージアクセスではアクセスできません。
Catインスタンスを作成し、そのスーパークラスタイプ、つまり動物タイプにキャストしました。 Animalタイプごとに、そのtestInstanceMethodは同じパッケージまたはサブタイプで表示されます。 Animal型にキャストしなかった場合、コードはコンパイルされます。
役立つことを願っています
./Arun