2つの異なるパッケージに2つのクラスがあります。
_package package1;
public class Class1 {
public void tryMePublic() {
}
protected void tryMeProtected() {
}
}
package package2;
import package1.Class1;
public class Class2 extends Class1 {
doNow() {
Class1 c = new Class1();
c.tryMeProtected(); // ERROR: tryMeProtected() has protected access in Class1
tryMeProtected(); // No error
}
}
_
_Class2
_は_Class1
_を継承しているため、このメソッドを見るので、tryMeProtected()
の呼び出しにエラーがない理由を理解できます。
しかし、なぜ_Class2
_のオブジェクトがc.tryMeProtected();
を使用して_Class1
_のオブジェクトのこのメソッドにアクセスできないのですか?
保護されたメソッドは、パッケージ外のサブクラスの継承によってのみアクセスできます。したがって、2番目のアプローチtryMeProtected();
が機能します。
以下のコードは、継承されたバージョンの保護されたメソッドを呼び出さないため、コンパイルできません。
Class1 c = new Class1();
c.tryMeProtected(); // ERROR: tryMeProtected() has protected access in Class1
詳細については、この stackoverflow リンクをたどってください。
package
とprotected
の可視性の違いを誤解していると思います。
package package1;
public class MyClass1 {
public void tryMePublic() { System.out.println("I'm public"); }
protected void tryMeProtected() { System.out.println("I'm protected"); }
void tryMePackage() { System.out.println("I'm package"); }
}
tryMePublic
はどこからでもアクセスできます。tryMeProtected
は、同じパッケージ内のすべてのサブクラスとすべてのクラスにアクセスできます。tryMePackage
は、同じパッケージのすべてのクラスにアクセスできます(異なるパッケージにある場合、子クラスでは使用できません)package package1;
public class Class2 extends MyClass1 {
public void doNow() {
tryMePublic(); // OK
tryMeProtected(); // OK
tryMePackage(); // OK
}
}
package package2;
import package1.MyClass1;
public class Class3 extends MyClass1 {
public void doNow() {
MyClass1 c = new MyClass1();
c.tryMeProtected() // ERROR, because only public methods are allowed to be called on class instance, whereever you are
tryMePublic(); // OK
tryMeProtected(); // OK
tryMePackage(); // ERROR
}
}
2つの異なるパッケージを使用し、直接継承によって親属性にアクセスするのではなく、子クラスで宣言された中間の親インスタンス(構成と同様)にアクセスします。 =>これはprotected
の動作方法ではありません。
直接継承のみが、保護された親の属性に到達できるようにします。
したがって、これを行うことができます:
public class Class2 extends Class1 {
doNow() {
tryMeProtected(); // No error since direct inheritance
}
}
しかし決してこれ:
public class Class2 extends Class1 {
doNow() {
Class1 c = new Class1();
c.tryMeProtected(); // this is not a direct inheritance! since `c`, although a parent one is an intermediate instance created in the child instance. => bad
}
}
実際、これはよく誤解されているprotected
keywordの特殊性です。
Javaのように、スーパークラスで保護されていると宣言されているProtected Access修飾子定義メソッドには、他のパッケージのサブクラスまたは保護されたメンバーのクラスのパッケージ内のクラスからのみアクセスできます。
クラスのオブジェクトを作成してプロテクトメソッドにアクセスすることはできません。したがって、Protectedメソッドにアクセスするには、スーパークラスを拡張する必要があります(これにより、2番目の呼び出しが正しいことがわかります)。
まず、2つのことを理解する必要があります。
1)パッケージ 'Y'のクラス 'X'のprotected
メンバー関数は、サブクラス、つまりそれを拡張するクラス(サブクラスが 'Y'以外のパッケージにある場合でも)からアクセスできます。それが理由です、
tryMeProtected(); // Showed no error because this was called by class 2 that is the subclass.
2)パッケージ 'Y'内のクラス 'X'のprotected
メンバー関数は、他のパッケージ内にある場合、それ自体ではアクセスできません。
[単純な例え:卵が巣1に保持されている鳥が巣2に飛んだ。巣2から、巣1に保持されている卵にアクセスできない。]同様に、クラスはそのメンバー関数にアクセスできません( publicで宣言されています。)他のパッケージ内にある場合。
それが理由です :
c.tryMeProtected(); // Showed error because this was called by class 1 reference.
// You can also think of it as class 1 cannot inherit itself.
保護された修飾子は1.Package Privateです2.他のパッケージのサブクラスから見ることができます。今の主な違い:
MyClass1 c = new MyClass1();
c.tryMeProtected();
そして
tryMyProtected();
継承ではなくMyClass1参照が使用されることです。 MyClass1は別のパッケージにあり、このコードはMyClass1から継承されていません。
それは2つの方法で達成することができます
1。Childクラスのオブジェクトを作成してから、Parentクラスのprotectedメソッドにアクセスします。
パッケージ1
_public class Class1 {
protected void m1() {
System.out.println("m1 called");
}
}
_
パッケージ2
_public class Class2 extends Class1 {
public static void main(String[] args) {
Class2 class2 = new Class2();
class2.m1();
}
}
_
2。または、子クラスからメソッドを直接呼び出すことにより
eg tryMeProtected();