今までの法則を使った例
問題
- GUI ライブラリの実装
- プラットフォームごとに呼び出し出すバックエンドのAPIが異なる
最初の実装 (例: WINDOW)
- 多重継承を多用
- WINDOW は GENERAL_WINDOW を継承
- 共通のコードを提供する暫定クラス
- プラットフォーム非依存
- WINDOW は PLATFORM_WINDOW も継承
- プラットフォーム依存の操作
- 各プラットフォーム毎に別ディレクトリで管理する
問題点
- 変更の法則に違反しないか?
- 基本的には問題ないはず
- 実行環境にプラットフォームは一つなので
- しかし、PostscriptやHTMLなどのバックエンドに拡張したら問題が起こりそうだ…!
- 実行環境ごとにプラットフォームが複数できるため
- 基本的には問題ないはず
- より関係のゆるい、顧客関係が望ましいかもしれない
改善案
- PLATFORM_WINDOW をやめる
- TOOLKIT 暫定クラスをアダプタとして用意する
- バックエンドの操作を提供
- MOTIF/MS_WINDOW などが TOOLKIT を実装
- WINDOW が各種 TOOLKIT の顧客となる
- WINDOW → TOOLKIT の参照は handle と呼ぶ
「なるほど、継承の濫用が間違っていたんだな!」
- …ということではない
- 事実うまくいっていた
- 多相的エンティティや動的束縛が使われている
分類マニアの法則
- 「すべての後継者は、新しい特性の追加、継承した特性の再宣言、または、不変表明句の追加を行わなければならない
無駄な分類レベルを追加することは自滅行為
- 親と後継者は、異なる抽象データ型を表していなければならない。
分類マニアが正しいケース
- 将来に備えるため
- 覆し用のない根拠がない限りはやるべきではない
例: PERSON と MALE / FEMALE
- female 属性を用意するのとどちらが良いか?
- 変種が増えるとあらゆる分岐で修正が発生する
- 人の性別を識別する必要があるのなら、この説明の前提である、それぞれの変種に固有の特性はない、という事に矛盾する(?)
- 今回の場合、変種が増えることはない
- (最近はそうとも言えないような)
- 分類する基準が途中で増えた場合
- 複数基準分類(この章で後述)
「全ての継承の使用は許されるカテゴリの一つに属さなければならない」
- 複数のカテゴリは禁止しないが、推奨しない
- 「である」関係ではなく単なる「がある」関係
- CAR_OWNER
- 区別する必要のある重要な特性が全くない
- 分類マニアの典型
- 便宜的継承
- 他のクラスの特性を再利用するだけのために継承する
- ただし再利用を否定しているわけではない
- モデル継承
- ソフトウェア継承
- バリエーション継承
互いに素なサブカテゴリに分類
- 親クラスは暫定クラスでなければならない
例: VERTEBRATE (脊椎動物)と MAMMAL (哺乳類) など
親クラスに不変表明を追加したものをサブクラスにする
- 双方とも暫定クラスか、双方とも有効でなければならない
例: RECTANGLE → SQUARE
暫定クラスの制約は、他の継承との区別をするためにある
親クラスに適用できない特性を追加する
- 親クラスは有効クラス
制約継承と一見矛盾する
例: POINT → MOVING_POINT、DOCUMENT → CHAPTER
- クラスをモデルするときに、属性の直積で考えない
- 代わりに、属性→値への部分関数とかんがえる
特性の再定義
- ファンクショナルバリエーション継承と型バリエーション継承がある
- 親子ともに暫定クラス
- もしくは親子ともに有効クラスで、かつ以下の条件を満たす場合
- 再定義で必要としない特性の追加がない
型バリエーション継承
- 特性のシグネチャだけを変更
- 型バリエーション継承では like を使うときは不要
ファンクショナルバリエーション継承では、実装方法を変更する
暫定特性への変更
一般的ではないが以下のケースでは使われる
- 多重継承をで、二つの特性を併合したい場合
- 親クラスの処理があまりに具体的すぎる場合
暫定クラスの特性の実装
例: TABLE → HASH_TABLE など
例: COMPARABLE → NUMERIC
特性のインポート
- 定数継承
- マシン継承