従来のクラス階層のよく知られた欠点は、実世界のモデリングに関しては悪いことです。例として、動物の種をクラスで表現しようとしています。実際にそれを行うといくつかの問題がありますが、解決策を見たことがないのは、サブクラスが、ペンギンが飛べないようなスーパークラスで定義された動作またはプロパティを「失う」場合ですおそらくより良い例ですが、それが私の頭に浮かぶ最初の例です)。
一方では、すべてのプロパティと動作について、それが存在するかどうかを指定するフラグを定義し、その動作またはプロパティにアクセスする前に毎回チェックする必要はありません。Birdクラスでは、鳥が簡単かつ明確に飛ぶことができると言いたいだけです。しかし、その後、どこか恐ろしいハックを使用することなく、「例外」を後で定義できればいいと思います。これは、システムがしばらくの間生産的だったときによく起こります。突然、元の設計にまったく適合しない「例外」が見つかり、それに対応するためにコードの大部分を変更する必要はありません。
それでは、「スーパークラス」とそれを使用するすべてのコードに大きな変更を加えることなく、この問題をきれいに処理できる言語または設計パターンがありますか?ソリューションが特定のケースのみを処理する場合でも、いくつかのソリューションが一緒になって完全な戦略を形成する場合があります。
もっと考えた後、リスコフの代替原則を忘れていたことに気付きました。それができない理由です。すべての主要な「機能グループ」に対して「特性/インターフェース」を定義すると仮定すると、階層のさまざまなブランチに特性を自由に実装できます。たとえば、Flying特性はBirds、いくつかの特殊なリスや魚によって実装できます。
したがって、私の質問は「どのようにして形質を実装しないのですか?」スーパークラスがJava Serializableである場合、たとえば「ソケット」が含まれている場合など、状態をシリアル化する方法がなくても、1つでなければなりません。
それを行う1つの方法は、最初から常にペアですべての特性を定義することです:FlyingとNotFlying(チェックしないとUnsupportedOperationExceptionがスローされます)。Not-traitは新しいインターフェースを定義せず、単純にチェックすることができます。特に最初から使用する場合、「安い」ソリューションのように聞こえます。
" it would be nice if one could define "exceptions" afterward, without having to use some horrible hacks everywhere"
ハッキング行動を制御するファクトリーメソッドを検討しますか?
NotSupportedException
fromをスローできPenguin.fly()
ます。
class Penguin < Bird; undef fly; end;
。あなたがすべきかどうかは別の質問です。
function save_yourself_from_crashing_airplane(Bird b) { f.fly() }
はありません」:動作を無効にすることは恐ろしいハックです。それはそれがはるかに複雑になることを意味します。(ピーターTörökが言ったように、それはLSPに違反しています)