C#およびC++/CLIでは、キーワードsealed
(またはVBのNotInheritable
)を使用して、クラスを継承の機会から保護します(クラスは継承できません)。オブジェクト指向プログラミングの1つの機能が継承であることを知っています。sealed
の使用はこの機能に反し、継承が停止すると感じています。 sealed
の利点と、それを使用することが重要な場合を示す例はありますか?
セキュリティ機能を実装するクラスで、元のオブジェクトを「偽装」できないようにします。
より一般的には、Microsoftの人と最近やり取りしました。彼は、継承を本当に意味のある場所に制限しようとしたと言ったのです。
sealedキーワードは、メソッドを探すためのクラスがこれ以上ないことをCLRに通知します。
現在市場に出回っているほとんどのパフォーマンス強化ツールには、継承されていないすべてのクラスを封印するチェックボックスがあります。
ただし、MEFを介したプラグインまたはアセンブリの検出を許可する場合は、問題が発生するため、注意してください。
Baboonの優れた答えの補遺:
関連するメモでは、非シールクラスにのみ適用可能です。virtual
で作成されたメソッドはすべて拡張ポイントであるか、少なくとも拡張ポイントであるように見えます。メソッドの宣言virtual
も同様に意識的に決定する必要があります。 (C#ではこれは意識的な決定です; Javaそうではありません。)
[〜#〜] edit [〜#〜]:いくつかの関連リンク:
Kotlin はデフォルトでクラスをシールすることにも注意してください。 そのopen
キーワードは、Javaのfinal
またはC#のsealed
の反対です 。 (確かに、 これが良いことであるという普遍的な合意はありません 。)
クラスをSealed
としてマークすると、セキュリティを損なったりパフォーマンスに影響を与える可能性のある重要なクラスの改ざんを防ぐことができます。
多くの場合、クラスを封印することは、変更したくない動作を固定したユーティリティクラスを設計するときにも意味があります。
たとえば、C#
のSystem
名前空間は、String
など、シールされた多くのクラスを提供します。封印されていない場合、その機能を拡張することができますが、これは特定の機能を備えた基本的なタイプであるため、望ましくない可能性があります。
同様に、C#
のstructures
は常に暗黙的にシールされます。したがって、1つの構造/クラスを別の構造から派生させることはできません。この理由は、structures
がスタンドアロン、アトミック、ユーザー定義データ型のみをモデル化するために使用されるためです。これは変更したくないものです。
クラス階層を構築しているときに、ドメインモデルまたはビジネスルールに基づいて、継承チェーン内の特定のブランチをキャップオフしたい場合があります。
たとえば、Manager
とPartTimeEmployee
は両方ともEmployee
sですが、組織のパートタイム従業員の後は役割を持ちません。この場合、さらに分岐しないようにPartTimeEmployee
をシールすることができます。一方、1時間ごとまたは1週間ごとにパートタイムの従業員がいる場合、PartTimeEmployee
からそれらを継承することは理にかなっているかもしれません。
この投稿にはいくつかの良い点があると思います。具体的なケースは、非密閉クラスを任意のインターフェイスにキャストしようとしたときに、コンパイラがエラーをスローしないことです。しかし、sealedが使用されると、コンパイラは変換できないエラーをスローします。シールドクラスは、追加のコードアクセスセキュリティをもたらします。
https://www.codeproject.com/Articles/239939/Csharp-Tweaks-Why-to-use-the-sealed-keyword-on-cla