[アイテム19]継承を考慮して設計し記録する.そうでなければ継承は禁止されます


  • プロジェクト18は継承を考慮せずに設計されており、継承時の注意事項も記録されていない外部クラス継承時のリスクを警告する(これは外部欄、プログラマーの制御権の外で、いつ何が変わるか分からないことを意味する)
  • 設計と記録の継承


  • メソッドを再定義する場合は、何が起こったのかを正確に特定するために、ドキュメントに残しておく必要があります.

  • 継承クラスは、内部で再定義可能なメソッドをどのように使用(自己使用)するかをドキュメントとして保持する必要があります.

  • クラスのAPIで開示されているメソッドからクラス独自の別のメソッドを呼び出すこともできますが、呼び出されたメソッドがちょうど機能メソッドを再定義している場合は、そのメソッドを呼び出すAPIの説明に明記する必要があります.

  • 呼び出し順序および各呼び出し結果が後続の処理に及ぼす影響も含まなければならない(publicおよびprotectedメソッドのすべてのメソッドが再定義され、finalではない)

  • 再定義可能なメソッドを呼び出すことができるすべての状況をドキュメントとして保持する必要があります.

  • クラスが安全に継承されていることを確認するには(継承されていない場合は説明すべきではない)、内部実装方法を説明する必要があります.

  • 内部メカニズムをドキュメントとして保持することは、設計のすべてを継承するものではありません.

  • 効率的なサブクラスを簡単に作成するには、クラスの内部操作中にクラスに挿入できるhook(hook)をフィルタリングし、protectedの方法で公開する必要がある場合があります.
  • は、protectedフィールド
  • を開示する必要は少ないかもしれない.

  • 継承するクラスを設計する際には、実際のサブクラスを作成し、実験によって予測し、方法をprotectedに暴露する必要があります.

  • protectedの方法は内部実施に適しているため、これらの方法をできるだけ少なく使用するとともに、露出が少なすぎることによる継承優位性の回避にも注意しなければならない.

  • 継承クラスをテストする唯一の方法は、独自のサブクラスを作成することです.

  • 必要なprotectedメンバーを逃した場合、サブクラスの作成時に空の場所が表示されます.
  • protectedを全く使用しないメンバーは、複数のサブクラスを作成する前にprivateである可能性が高い.

  • 広く使用されているクラスを継承するように設計されている場合、protectedメソッドおよびフィールドを実装する過程で、決定は常に責任を負います.

  • 継承のために設計されたクラスは、デプロイ前にサブクラスを作成して検証する必要があります.
  • ふふ?

    Hook(Hook)


    Hook(Hook)は、抽象クラスでアクションを実行したりデフォルトの動作を定義したりするのではなく、サブクラスで上書きできる定義です.
    これを選んで、本の例から見ると
    public class Super {
    		// 잘못된 예 - 생성자가 재정의 가능 메서드를 호출함
    		public Super() {
    				overrideMe();
    		}
    
    		public void overrideMe() {
    		}
    }
    public final class Sub extends Super {
    		// 초기화되지 않은 final 필드. 생성자에서 초기화한다.
    		private final Instant instant;
    
    		Sub() {
    				instant = Instant.now();
    		}
    
    		// 재정의 가능 메서드. 상위 클래스의 생성자가 호출한다.
    		@Override public void overrideMe() {
    				System.out.println(instant);
    		}
    
    		public static void main(String[] args) {
    				Sub sub = new Sub();
    				sub.overrideMe();
    		}
    }
    ここで、親クラスの作成者も呼び出されたときにoverrideMeを呼び出します.この方法は再定義によって埋め込むことができますが、それ以前は何もしていなかった方法です.
    上記の場合は、内部操作中にhookが挿入される可能性があることを意味し、実際には上記の例overrideMeの方法は何もしないので、親の構造関数はnullとして出力されることがよく理解され、protectedを処理することを意味する

    継承を許可するクラスが守らなければならない制約


  • 継承クラスの作成者は、再定義可能なメソッドを直接または間接的に呼び出すべきではありません.そうしないと、プログラムがエラーになります.

  • 親クラスの作成者は、子クラスの作成者よりも先に実行されるため、子クラスで再定義されたメソッドは、子クラスの作成者よりも前に呼び出されます.

  • 再定義されたメソッドが、サブクラスの作成者で初期化された値に依存する場合、予想通りに動作しません.

  • 例は以下の通りです
    public class Super {
    		// 잘못된 예 - 생성자가 재정의 가능 메서드를 호출함
    		public Super() {
    				overrideMe();
    		}
    
    		public void overrideMe() {
    		}
    }
    public final class Sub extends Super {
    		// 초기화되지 않은 final 필드. 생성자에서 초기화한다.
    		private final Instant instant;
    
    		Sub() {
    				instant = Instant.now();
    		}
    
    		// 재정의 가능 메서드. 상위 클래스의 생성자가 호출한다.
    		@Override public void overrideMe() {
    				System.out.println(instant);
    		}
    
    		public static void main(String[] args) {
    				Sub sub = new Sub();
    				sub.overrideMe();
    		}
    }

  • 上記の親クラスの作成者は、子クラスの作成者がインスタンスフィールドを初期化する前にoverrideMeを呼び出し、nullを最初に出力する
  • printlnはnull入力も受け付けているのでNullPointerExceptionは放出されません
  • privatefinalstaticメソッドは再定義できないので、安心してジェネレータから呼び出すことができる
  • CloneableおよびSerializableインタフェースは、継承性設計の難易度をさらに高め、継承可能なクラスを設計することは通常、このクラスを拡張したいプログラマーに大きな負担をもたらす悪いアイデアである.
  • cloneメソッドとreadObjectメソッドの効果はジェネレータと似ています(新しいオブジェクトを作成)

  • 継承クラスでCloneableおよびSerializableを実装するように指定する必要がある場合は、それらを実装する際に従う制約もコンストラクション関数と同様であることに注意してください.
  • cloneおよびreadObjectは、再定義可能なメソッドを直接または間接的に呼び出すことはできません.
  • readObjectでは、サブクラスのステータスは、複数のドメインにシーケンス化されるまで、再定義されたメソッドから呼び出されます.
  • cloneの場合、サブクラスのcloneメソッドは、レプリカのステータス(正しいステータス)を変更する前に再定義されたメソッドを呼び出す.

  • どちらの場合もプログラムエラーが発生します
  • cloneも元のオブジェクトを損なう
  • Serializableを実装する継承クラスがreadResolveまたはwriteReplaceメソッドを有する場合、これらのメソッドはprivateではなくprotectedとして宣言されるべきである.
  • 一般的なクラス


  • これらのクラスはfinalではなく、継承のために設計または記録されたものではありません.

  • これは,一定に保つとクラスが変化するたびにサブクラスにエラー動作が発生するためである.

  • この場合、継承として設計されていないクラスの継承を禁止することが最善の方法です.
  • 継承を禁止する方法


  • 宣言クラスはfinalです

  • すべてのジェネレータをprivateまたはpackage-privateと宣言し、publicの静的ファクトリを作成する方法

  • アイテム18に記載されたRapperクラスモードも、機能を強化する際に継承を代替するより良い代替案である.
  • どうしてもやるなら。


  • クラスで再定義可能なメソッドを無効にし、この事実をドキュメントとして保持します.

  • 再定義可能なメソッドを呼び出す磁気コードを完全に削除

  • クラスの動作を維持しながら再定義可能なメソッドを使用するコードを削除する機械的メソッドは、まず、各再定義可能なメソッドがその本文コードをprivateヘルプメソッドに移動し、このヘルプメソッドを呼び出すように変更することです.

  • その後、呼び出し再定義可能なメソッドの他のすべてのコードを変更して、このアシスタントメソッドを直接呼び出すことができます.