web-dev-qa-db-ja.com

別のパッケージのサブクラスが保護されたメソッドにアクセスできないのはなぜですか?

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_のオブジェクトのこのメソッドにアクセスできないのですか?

15
user2986848

保護されたメソッドは、パッケージ外のサブクラスの継承によってのみアクセスできます。したがって、2番目のアプローチtryMeProtected();が機能します。

以下のコードは、継承されたバージョンの保護されたメソッドを呼び出さないため、コンパイルできません。

 Class1 c = new Class1();
 c.tryMeProtected(); // ERROR: tryMeProtected() has protected access in Class1

詳細については、この stackoverflow リンクをたどってください。

14
Ankur Shanbhag

packageprotectedの可視性の違いを誤解していると思います。

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
    }    
}
10
Anthony Raymond

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
    }    
}

実際、これはよく誤解されているprotectedkeywordの特殊性です。

3
Mik378

Javaのように、スーパークラスで保護されていると宣言されているProtected Access修飾子定義メソッドには、他のパッケージのサブクラスまたは保護されたメンバーのクラスのパッケージ内のクラスからのみアクセスできます。

クラスのオブジェクトを作成してプロテクトメソッドにアクセスすることはできません。したがって、Protectedメソッドにアクセスするには、スーパークラスを拡張する必要があります(これにより、2番目の呼び出しが正しいことがわかります)。

1
Tushar D

まず、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.
0
Dewansh Nigam

保護された修飾子は1.Package Privateです2.他のパッケージのサブクラスから見ることができます。今の主な違い:

MyClass1 c = new MyClass1();
    c.tryMeProtected();

そして

tryMyProtected(); 

継承ではなくMyClass1参照が使用されることです。 MyClass1は別のパッケージにあり、このコードはMyClass1から継承されていません。

0
Nora alshareef

それは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();

0
Satyam