権限修飾子の理解


今日、私は次のような文を見ました。「抽象クラスの抽象メソッドは、パブリック/保護/デフォルトのアクセス修飾子で装飾できます。インターフェイスの抽象メソッドは、デフォルトでパブリックアクセス修飾子であり、他のアクセス修飾子は使用できません。フー、「アクセスモディファイアをサポートする同じ抽象的な方法が同じではないのはなぜだろうか?

これは考えであり、規制であり、一時的に理解できないとインターネット上で言われています。
最初に考えたのは、4つのアクセス修飾子の範囲を完全に理解していないかどうかだったので、アクセス許可修飾子を比較するデモを作成することにしました(結果は完全には理解されていませんが、そうではありません)この質問への回答は、完全な理解がない場合は後で拡張されます)

まず、シナリオを使って理解する方法についてお話します。
インターネットによると、「インターフェースは、主にモジュール間の通信契約を定義するために使用されるシステムアーキテクチャの設計方法でより多くの役割を果たします。また、抽象クラスは、主にコードの再利用を実現するために使用されるコードの実装において役割を果たします。
前の文について、プロジェクト担当者Aは、プロジェクト担当者Bがビジネスモジュールに実装するためにパッケージ化された、いくつかのインターフェイスを宣言するAPIモジュールを作成しました。Aがデフォルトの修飾子を使用してインターフェイスの抽象メソッドを変更する場合、Bはアクセスできない必要があります。この抽象的な方法は、それを書き直すことは言うまでもありません。
パブリック以外のアクセス修飾子はインターフェイスで使用できないため、次のビジネスシナリオは抽象クラスに置き換えられます

public abstract class UserApi{
    
    
    abstract void login();
}

次に、インターフェイスが別のモジュールの下に実装され、エラーが見つかりました。

Aはインターフェイスを書き込みます。目的は、Bがそれを実現できるようにすることですが、上記のテストによると、デフォルトのアクセス修飾子をインターフェイスで使用できる場合、Bはそれを実装できないことがわかります。これは明らかに当初の意図と一致していません。使用する必要はありません。抽象クラスの使用シナリオは、ここでは試していません。

次は今の誤解ですが、異なるパッケージのサブクラスが親クラスの保護されたメンバーにアクセスできないのはなぜですか?
アクセスモディファイアの範囲はインターネットで検索でき、おおよそ次の要約のようになります。デモの作成中に、赤いボックスの位置が正しくないことがわかりました。
ここに写真の説明を挿入
コードは次のとおりです。

public class Father {
    
    

    public void m1() {
    
    
    }

    protected void m2() {
    
    
    }

    void m3() {
    
    
    }

    private void m4() {
    
    
    }

}

異なるパッケージのサブクラスは、親クラスの保護されたメソッドにアクセスできないことが判明しました...恥ずかしいです。
ここに写真の説明を挿入
この結果は、異なるパッケージの無関係なクラスの結果とまったく同じです。
ここに写真の説明を挿入
最後に、使用方法に問題があることを学びました。実際に写真を使用できます。アクセス許可の範囲は明確に記載されていますが、アクセス方法を理解していない場合でも、上記の問題が発生します。さまざまなパッケージでの正しいサブクラスコードは次のとおり
ここに写真の説明を挿入
です。アクセス許可の関連コードは、すべての人が
このパッケージをプレイできるように添付されています。下:

package com.test;

public class Father {
    
    //若不声明为public,则不同包下子类访问不到,无法继承

    public void m1() {
    
    
    }

    protected void m2() {
    
    
    }

    void m3() {
    
    
    }

    private void m4() {
    
    
    }

    //本类下访问
    public void m() {
    
    
        m1();
        m2();
        m3();
        m4();
        //若方法m1m2m3m4都为static类型,则各类的m方法中通过Father.的方式也可以达到相同结果
    }
}

class SonInTheSamePackage extends Father {
    
    

    //相同包下子类访问
    public void m() {
    
    
        m1();
        m2();
        m3();
        m4();//Father里被private修饰的方法报错
    }
}

class UnrelatedClassInTheSamePackage {
    
    

    //相同包下无关类访问
    public void m() {
    
    
        Father father = new Father();
        father.m1();
        father.m2();
        father.m3();
        father.m4();//Father里被private修饰的方法报错
    }
}

他のパッケージの下で:

package com.test2;

import com.test.Father;

class SonInDifferentPackage extends Father {
    
    

    //不同包下子类访问
    public void m() {
    
    
        m1();
        m2();
        m3();//Father里被默认修饰符修饰的方法报错
        m4();//Father里被private修饰的方法报错
    }
}

class UnrelatedClassInDifferentPackage {
    
    

    //不同包下无关类访问
    public void m() {
    
    
        Father father = new Father();
        father.m1();
        father.m2();//Father里被protected修饰的方法报错
        father.m3();//Father里被默认修饰符修饰的方法报错
        father.m4();//Father里被private修饰的方法报错
    }
}

最後に、別の質問があります。異なるパッケージで新しいFather()を介したm2()へのアクセスが失敗する理由(つまり、上記の私の誤解)ですが、m2が静的として変更された場合、正常にアクセスできます(静的クラス名、静的メソッド、またはインスタンスオブジェクトの後、静的メソッドに正常にアクセスできます。これが前者の失敗と比較されるのはなぜですか(ただし、異なるパッケージの下の無関係なクラスは引き続きアクセスできません))
このパッケージの下で:

package com.test;

public class Father {
    
    

    protected static void m2() {
    
    
    }

}

他のパッケージの下で:

package com.test2;

import com.test.Father;

class SonInDifferentPackage extends Father {
    
    

    //不同包下子类访问
    public void m() {
    
    
        Father father = new Father();
        father.m2();//不报错
        Father.m2();//不报错
    }
}

class UnrelatedClassInDifferentPackage {
    
    

    //不同包下无关类访问
    public void m() {
    
    
        Father father = new Father();
        father.m2();//报错
        Father.m2();//报错
    }
}

実際、それはまだそれをどのように使用するかという問題です。サブクラスの下のアクセスは、新しいサブクラスオブジェクトに移動してから、アクセスする(または直接呼び出す)必要があります。サブクラスの新しい親オブジェクトにアクセスする代わりに!
ただし、無関係なクラスは、新しいサブクラスオブジェクトまたは親クラスオブジェクトに移動してからアクセスすると、結果は同じになります。
このパッケージでは、次のようになります。

package com.example.demo.test;

public class Father {
    
    

    protected void m2() {
    
    
    }

}

その他のパッケージ:

package com.example.demo.test2;

import com.example.demo.test.Father;

class SonInDifferentPackage extends Father {
    
    

    //不同包下子类访问
    public void m() {
    
    
        Father father = new Father();
        father.m2();//报错
        SonInDifferentPackage son = new SonInDifferentPackage();
        son.m2();//不报错
        m2();//不报错
    }
}

class UnrelatedClassInDifferentPackage {
    
    

    //不同包下无关类访问
    public void m() {
    
    
        Father father = new Father();
        father.m2();//报错
        SonInDifferentPackage son = new SonInDifferentPackage();
        son.m2();//报错
    }
}

とにかく、書くのは少し冗長です、それはちょうどそのような状況を行ったり来たりすることです、あなたが私を許してくれることを願っています!

おすすめ

転載: blog.csdn.net/weixin_44463178/article/details/108765610