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