私は多くの人がクラスのあるべき感じる本当の理由は信じてfinal
/ sealed
その最も非抽象拡張クラスがされているではない、適切に文書化。
詳しく説明させてください。遠くから始めて、OOPのツールとしての継承が広く使われ、乱用されているという意見が一部のプログラマーにあります。私たちは皆、リスコフ置換の原則を読みましたが、これは何百回(おそらくは数千回)違反することを止めるものではありませんでした。
問題は、プログラマーがコードを再利用することです。それがそんなに良い考えではない時でさえ。そして、継承はこのコードの「改ざん」における重要なツールです。最終/封印された質問に戻ります。
final / sealedクラスの適切なドキュメントは比較的小さく、各メソッドの動作、引数、戻り値などを記述します。すべての通常のもの。
ただし、拡張可能クラスを適切に文書化する場合は、少なくとも次のものを含める必要があります。
- メソッド間の依存関係(どのメソッドがどのメソッドを呼び出すかなど)
- ローカル変数への依存関係
- 拡張クラスが尊重すべき内部契約
- 各メソッドの呼び出し規則(たとえば、オーバーライドするとき、
super
実装を呼び出しますか?メソッドの最初に呼び出しますか、それとも最後に呼び出しますか?コンストラクターとデストラクターを考えます)
- ...
これらは私の頭上にあります。そして、これらのそれぞれが重要であり、それをスキップすると拡張クラスが台無しになる理由の例を提供できます。
次に、これらの各事項を適切に文書化するためにどれだけの文書化努力が必要かを検討します。7〜8個のメソッド(理想化された世界では多すぎるかもしれませんが、実際には少なすぎる)を持つクラスには、テキストのみの5ページに関するドキュメントも含まれていると思います。したがって、代わりに、他の人が使用できるようにクラスを途中で閉じて封印しませんが、巨大な時間がかかるため、適切に文書化しないでくださいとにかく延長されることはありませんので、なぜわざわざ?
クラスを設計している場合、あなたが予見していない(そして準備していない)方法で人々がそれを使用できないように、それを封印する誘惑を感じるかもしれません。一方、他の人のコードを使用している場合、パブリックAPIからは、クラスが最終的なものであるという明らかな理由がない場合があります。
ソリューションの要素には次のものがあると思います。
- ことを確認する最初の拡張は良いアイデアですあなたは、コードのクライアントにいるとき、およびするために実際に相続以上の組成を好みます。
- 次に、マニュアルを完全に(クライアントとして)読んで、言及されていることを見落とさないようにします。
- 第三に、クライアントが使用するコードの一部を作成するときは、コードの適切なドキュメントを作成します(そう、長い道のりです)。良い例として、AppleのiOSドキュメントを提供できます。常に適切に自分のクラスを拡張するために彼らは、ユーザーのためには十分ではないですが、彼らは少なくとも含まれ、いくつかの継承についての情報を。これは、ほとんどのAPIで言える以上のことです。
- 第4に、実際にクラスを拡張して、機能することを確認してください。私はAPIに多くのサンプルとテストを含めることを大いに支持しています。テストを行うとき、継承チェーンもテストするかもしれません。それらは結局あなたの契約の一部です!
- 第5に、疑わしい状況では、クラスが拡張されることを意図しておらず、それを行うのは悪い考え(tm)であることを示します。そのような意図しない使用については説明責任を負わせてはいけませんが、それでもクラスを封印しないでください。明らかに、これはクラスを100%封印する必要がある場合をカバーしません。
- 最後に、クラスを封印するとき、中間フックとしてインターフェースを提供します。これにより、クライアントはクラスの独自の修正バージョンを「書き換え」、「封印された」クラスを回避できます。この方法で、彼は封印されたクラスを実装に置き換えることができます。これは、最も単純な形式では疎結合であるため、これは明らかなはずですが、それでも言及する価値があります。
また、次の「哲学的」問題に言及する価値がある:クラスがあるかどうかであるsealed
/ final
クラスの契約、または実装の詳細の一部?今、私はそこを踏み込みたくありませんが、これに対する答えは、クラスを封印するかどうかのあなたの決定にも影響を与えるはずです。
Open/Closed principle
ではなく、と呼ばれているためClosed Principle.