単品クラスとメンバーのアクセス権の最小化


単品クラスとメンバーのアクセス権の最小化


設計が悪い素子と設計が良い素子の最大の違いは,クラス内部データと内部実装情報が外部素子にどれだけ隠されているかである.丹念に設計されたコンポーネントは、すべての内部インプリメンテーションを非表示にし、インプリメンテーションをAPIから分離します。APIを通じて他のコンポーネントとコミュニケーションするだけで、お互いの内部操作方式に関心がありません。情報を隠すか、パッケージ化するか、この概念はソフトウェア設計の基礎である。

情報を隠すメリット


情報を隠すメリットは本当に多いです.その大部分は、システムを構成する要素とは独立しており、開発、テスト、最適化、応用、分析、および修正を単独で行うことができる.

システム開発のスピードを速める。


複数の構成部品を並列に開発できるからです.

システム管理費用を削減する。


これは、各構成部品をより迅速に理解し、デバッグし、他の構成部品に影響を与えることなく、これらの構成部品のみを最適化できるためです.

ソフトウェアの再利用性の向上


外部にほとんど依存せずに独立して動作する素子であれば,その素子とともに開発されていない見慣れない環境でも有用である可能性が高いからである.

大きなシステムを作る難易度を下げる。


システム全体が完了していなくても、各素子の挙動を検証することができるからである.

アクセス制限

  • Javaは、多くの非表示情報を提供するデバイスを提供します.アクセス制御メカニズムは、クラス、インタフェース、およびメンバーのアクセス性(アクセス可能な範囲)を示します.
  • 各要素のアクセス性は、宣言された場所およびアクセス制限者(private、protected、public)によって決定される.このアクセス制限者を正しく利用することは、情報を隠す核心です.
  • 基本原則


    基本原則は簡単だ.すべてのクラスとメンバーのアクセス性をできるだけ縮小します.これは、ソフトウェアが正常に動作している限り、常に最小限のアクセスレベルを付与する必要があることを意味します.
  • (最も外側の意味)トップクラスクラスとインタフェースのアクセスレベルはpackage-privateとpublicの2種類があります.
  • のトップクラスまたはインタフェースが共通として宣言された場合、公開APIとなります.package-privateとして宣言された場合、パッケージでのみ使用できます.
  • コース外で使用する理由がなければpackage-privateと宣言します.これにより、APIではなく、内部実装となり、いつでも変更できます.
  • とは逆に、公表されればAPIとなるため、互換性を低くするためには常に管理しなければならない.
  • 1つのクラスでのみ使用されるpackage-privateトップクラスまたはインタフェースについて、使用するクラスのprivate staticにネストしてみます.
  • トップレベルを維持すると、同じパッケージ内のすべてのクラスにアクセスできますが、private staticとしてネストされている場合は、1つの外部クラスからのみアクセスできます.
  • 共通クラスはそのパッケージのAPIであり、package-privateトップクラスクラスは内部実装に属する.したがって、クラスのアクセスレベルを公開することなくprivateにできるだけパッケージ化できます.
    最上位レベルに縮小します.
  • メンバーおよびアクセス・レベル


    メンバー(フィールド、メソッド、ネストされたクラス、ネストされたインタフェース)に4つのアクセスレベルを付与できます.
  • private:宣言メンバーの上位クラスにのみアクセスできます.
  • package-private:メンバーは、所属するパッケージ内のすべてのクラスからアクセスできます.アクセス制限者が指定されていない場合に適用されるパケットアクセスレベル(ただし、インタフェースのメンバーは基本的にpublic
    適用されます).
  • protected:package-privateのアクセス範囲を含むか、メンバーを宣言するクラスのサブクラスからアクセスすることもできます.
  • 公共:どこからでも近づくことができます.
  • クラスとアクセス範囲

  • クラスの公開API以外のすべてのメンバーはプライベート化されます.
  • は、同じパッケージの他のクラスにアクセスする必要があるメンバーに限定され、package-privateに解凍されます.
  • 権限を解放することをよくする場合は、素子をさらに分解する必要があるかどうかを再考する必要があります.
  • privateメンバーとpackage-privateメンバーは、通常、公開APIに影響を与えないクラスのインプリメンテーションに属します.
  • セグメントは、シリアル化を実現するクラスにおいて、これらのフィールドが意図的に公開APIになることもある.
  • 共通クラスと保護されたクラス

  • 共通クラスで、package-privateからprotectedにメンバーのアクセスレベルを変換すると、そのメンバーにアクセスできるオブジェクトの範囲が非常に大きくなります.
  • 共通クラスの保護されたメンバーは公開APIであり、常にサポートが必要である.
  • はまた、内部操作方式をAPIドキュメントに書き込み、ユーザに公開する必要がある場合もある.したがって、保護されたメンバーの数が少ないほど良い.
  • メンバーのアクセス制限

  • 親クラスのメソッドを再定義する場合、親クラスでより狭いアクセスレベルに設定することはできません.
  • この制約は、親クラスのインスタンスがクラスのインスタンスに置き換えられて使用される必要があるというルール(リスク交換の原則)を遵守するためです.
  • がルールに違反した場合、サブクラスをコンパイルするときにコンパイルエラーが発生します.
  • クラス実装インタフェースは、クラスがインタフェース定義のすべてのメソッドを共通として宣言する必要があるルールの特別な例と見なすことができる.
  • テストとアクセス範囲

  • テストのみのクラス、インタフェース、およびメンバーを公開APIとして作成することはできません.
  • のテストコードとテストオブジェクトを同じパッケージに配置し、package-private要素にアクセスできます.
  • 共通クラスとインスタンスフィールド

  • 共通クラスのインスタンスフィールドは、できるだけ共通ではありません.
  • フィールドが可変オブジェクトを参照する場合、または非finalインスタンスフィールドをpublicとして宣言する場合、フィールドに値を含めることができることを制限する能力は失われます.
  • フィールドに関連するすべてのコンテンツは不変性を保証することができず、フィールドが変更されると(ロックを取得するなど)他の操作ができないため、共通の可変フィールドを持つクラスは通常スレッドセキュリティを持たない.
  • は静的フィールドにおいても同様であるが、クラスが表現する抽象概念を完了するために必要なコンポーネントの定数としてpublic static finalフィールドとして開示することができる.
  • これらのフィールドは、デフォルトのタイプ値または不変のオブジェクトを参照する必要があります.
  • が可変オブジェクトを参照する場合、非finalフィールドに適用されるすべての不利な要素が受け入れられる.
  • 他のオブジェクトは参照できませんが、参照するオブジェクト自体が変更される可能性があります.

    整列

    // 보안 허점이 숨어 있다.
    public static final Thing[] VALUES = {...};
  • 長さゼロの配列は変更可能ですので注意してください.したがって、クラスに共通の静的final配列フィールドを配置したり、そのフィールドを返すアクセス者メソッドを提供したりすることはできません.
  • これには2つの解決方法がある.
  • の最初の解決策は、共通レイアウトをプライベート化し、共通不変リストを追加することである.
  • private static final Thing[] PRIVATE_VALUES = { ... };
    public static final List<Thing> VALUES = Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));
  • の第2の解決策は、配列をプライベート化し、そのコピーを返す共通の方法(防御レプリケーション)を追加することである.
  • private static final Thing[] PRIVATE_VALUES = { ... };
    public static final Thing[] values() {
        return PRIVATE_VALUES.clone();
    }

    Java 9に追加されたモジュールシステムとアクセスレベル

  • java 9は、モジュールシステムの概念を導入し、2つのデフォルトアクセスレベルを追加しました.
  • パッケージがクラスの集合であるように、モジュールはパッケージの集合である.モジュールは、自分のパッケージに公開(エクスポート)する内容を宣言します(通常はmodule-info.javaファイル).
  • が保護されているか、パブリックメンバーがパッケージを公開していない場合は、モジュールの外部からアクセスできません.
  • モジュール内で、エクスポートに影響を及ぼさないと宣言したかどうか.
  • モジュールシステムを使用すると、クラスを公開せずに、同じモジュールを構成するパッケージ間でクラスを自由に共有できます.
  • ... 詳しい内容は後で必要な時に参考書にします.

    コアの整理


    プログラム要素のアクセス性はできるだけ小さくします.必要な、最も少ない設計の共通APIのみを選択します.それ以外に、クラス、インタフェース、メンバーを意外にAPIで公開しないでください.
    publicクラスには、定数のpublic static finalフィールドでない限り、publicフィールドは存在しないでください.
    public static finalフィールドが参照するオブジェクトが変わらないことを確認します.