14

以下の例(保護されたメンバーがサブクラスを介してパッケージの外部からアクセスされている場合)で何が起こっているのかを理解したいと思います。

パッケージ外のクラスの場合、サブクラスは継承を通じてのみ保護されたメンバーを見ることができます。

2つのパッケージがあります:package1package2

  1. package1ProtectedClass.java

    package org.test.package1;
    
    public class ProtectedClass {
    
        protected void foo () {
            System.out.println("foo");
        }
    }
    
  2. package2ExtendsprotectedClass.java

    package org.test.package2;
    
    import org.test.package1.ProtectedClass;
    
    public class ExtendsprotectedClass  extends ProtectedClass {
    
        public void boo() {
            foo(); // This works, 
                   // since protected method is visible through inheritance
        }
    
        public static void main(String[] args) {
            ExtendsprotectedClass epc = new ExtendsprotectedClass();
            epc.foo(); // Why is this working? 
                       // Since it is accessed through a reference,
                       // foo() should not be visible, right?
        }
    }
    
  3. package2UsesExtendedClass.java

    package org.test.package2;
    
    public class UsesExtendedClass {
    
        public static void main(String[] args) {
            ExtendsprotectedClass epc = new ExtendsprotectedClass();
            epc.foo(); // CompilationError: 
                       // The method foo() from the type ProtectedClass
                       // is not visible
        }
    }
    

保護されたメンバーは継承を通じてのみアクセスできるため、のboo()メソッドはにExtendsprotectedClassアクセスできることが理解されます。foo()

私の質問は、メソッドの参照を介してアクセスするとメソッドが 正常foo()に機能するのに、の参照を介してアクセスすると機能しないのはなぜですか?main()ExtendsprotectedClassepcUsesExtendedClass

4

4 に答える 4

12

クラス内のコードは、タイプの参照を介してのExtendsprotectedClass保護されたメンバーにアクセスできます。JLSセクション6.6.2から:ProtectedClassExtendsprotectedClass

オブジェクトの保護されたメンバーまたはコンストラクターは、そのオブジェクトの実装を担当するコードによってのみ宣言されているパッケージの外部からアクセスできます。

保護されたメンバーmが宣言されているクラスをCとします。アクセスは、CのサブクラスSの本体内でのみ許可されます。さらに、Idがインスタンスフィールドまたはインスタンスメソッドを示す場合、次のようになります。

  • アクセスが修飾名Q.Id(QはExpressionName)による場合、式QのタイプがSまたはSのサブクラスである場合にのみ、アクセスが許可されます。[...]

UsesExtendedClassの実装には責任がないExtendsprotectedClassため、最後の呼び出しは失敗します。

編集:この背後にある理由は、protectedアクセスはサブクラスが必要な機能を実装するのを助けるように設計されており、通常利用できるよりも多くのスーパークラスの内部へのアクセスを提供するということです。それがすべてのコードで利用可能であれば、メソッドを公開するのにかなり近いでしょう。基本的に、サブクラスはカプセル化を破らないと信頼されています。独自のタイプのオブジェクト内でより多くの機能が提供されます。パブリックAPIはこれらの詳細を公開するべきではありませんが、保護されたAPIは、サブクラスにより多くの機会を与える目的でのみ使用できます。

于 2010-08-22T07:57:16.150 に答える
2

最初のケースでは、メソッドが参照を介してアクセスされている場合でも、同じクラスから呼び出されているため、機能しています。同じメインメソッド内の参照privateを介してのメソッドを呼び出すこともできます。ExtendsprotectedClass

于 2010-08-22T09:23:03.067 に答える
1

あなたはあなた自身の質問に答えたと思います。UsesExtendedClassはProtectedClassを継承しません。また、定義上、「保護された」メンバーは、宣言/定義されたクラス、または宣言または定義されたクラスから継承したクラスでのみアクセスできます。

于 2010-08-22T07:58:55.297 に答える
0

http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.htmlからこの写真を見てください。

ここに画像の説明を入力してください

クラスの保護されたメンバーがサブクラスを介してアクセスできることは明らかです。

于 2014-04-30T20:19:26.490 に答える