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