Java で継承を禁止する正当な理由は何ですか?たとえば、最終クラスを使用するか、単一のプライベート パラメーターなしのコンストラクターを使用するクラスを使用することによりますか? メソッドを final にする正当な理由は何ですか?
11 に答える
ここで最も参考になるのは、Joshua Bloch の優れた本「Effective Java」の項目 19 で、「継承または禁止するための設計と文書」と呼ばれています。(第2版では17項、初版では15項です。) 本当に読んでいただきたいのですが、まとめておきます。
祖先が継承されるように設計されていない場合、継承されたクラスとその親との相互作用は驚くべきものであり、予測不可能になる可能性があります。
したがって、クラスには次の 2 種類があります。
拡張できるように設計されたクラスで、拡張方法を説明する十分なドキュメントが用意されている
最終とマークされたクラス
純粋に内部コードを書いている場合、これは少しやり過ぎかもしれません。ただし、クラス ファイルに 5 文字を追加するのに必要な余分な作業はごくわずかです。内部消費のみを目的として記述している場合、将来のコーダーはいつでも「最終」を削除できます。これは、「このクラスは継承を念頭に置いて設計されていません」という警告と考えることができます。
クラスをオーバーライドしても、他のメソッドで期待されている動作を変更できないように、メソッドを final にしたい場合があります。コンストラクターで呼び出されるメソッドは多くの場合 final と宣言されるため、オブジェクトを作成するときに不愉快な驚きはありません。
クラスを final にする理由の 1 つは、継承よりも合成を強制したい場合です。これは通常、クラス間の密結合を避けるために望ましいことです。
不変オブジェクト(http://en.wikipedia.org/wiki/Immutable_object)、シングルトン(http://en.wikipedia.org/wiki/Singleton_pattern)、または効率、安全性、またはセキュリティの理由で誰かがメソッドをオーバーライドするのを防ぐため。
継承はチェーンソーのようなものです。非常に強力ですが、悪用すると恐ろしいものです。継承元のクラスを設計する (柔軟性が制限され、時間がかかる可能性があります) か、禁止する必要があります。
有効な Java 2nd エディションの項目 16 と 17、または私のブログ記事「相続税」を参照してください。
うーん... 2 つのことが考えられます。
特定のセキュリティ問題を扱うクラスがあるかもしれません。それをサブクラス化し、サブクラス化されたバージョンをシステムに供給することにより、攻撃者はセキュリティ制限を回避できます。たとえば、アプリケーションがプラグインをサポートしていて、プラグインがセキュリティ関連のクラスをサブクラス化できる場合、このトリックを使用してサブクラス化されたバージョンを適切な場所に密輸することができます。ただし、これは Sun がアプレットなどに関して対処しなければならないことであり、おそらくそれほど現実的なケースではありません。
より現実的な方法は、オブジェクトが可変になるのを避けることです。たとえば、文字列は不変であるため、コードはそれへの参照を安全に保持できます
String blah = someOtherString;
最初に文字列をコピーする代わりに。ただし、String をサブクラス化できる場合は、文字列値を変更できるようにするメソッドを追加できます。これで、上記のように文字列をコピーするだけで文字列が同じままであることに依存するコードはもうありません。代わりに、文字列を複製する必要があります。ストリング。
人々が自分自身や他の人を混乱させるようなことをするのを止めること. いくつかの定数や計算が定義されている物理ライブラリを想像してみてください。final キーワードを使用しないと、誰かがやって来て、絶対に変更してはならない基本的な計算や定数を再定義する可能性があります。
クラスとメソッドをfinalとしてマークすると、ランタイムが特定のオブジェクトに対して呼び出すために適切なクラスメソッドを検索する必要がないため、パフォーマンスがわずかに向上することに気付く場合があります。非finalメソッドは仮想としてマークされているため、必要に応じて適切に拡張できます。finalメソッドは、クラス内で直接リンクまたはインラインでコンパイルできます。
また、商用のクローズド ソース クラスを作成している場合、特にそのサポートを提供する必要があり、人々がメソッドをオーバーライドして、それを呼び出すと予想外の結果。
クラスをオーバーライドしても動作が変わらないように、メソッドを final にする必要があります。動作を変更できるようにしたい場合は、メソッドを公開します。public メソッドをオーバーライドすると、変更できます。