Skip to content

Instantly share code, notes, and snippets.

@wm3
Created January 20, 2015 10:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wm3/c3dfc1f54a98b5943baa to your computer and use it in GitHub Desktop.
Save wm3/c3dfc1f54a98b5943baa to your computer and use it in GitHub Desktop.
24.md

24.3 応用: handle (ハンドル)という技法

今までの法則を使った例

問題

  • GUI ライブラリの実装
  • プラットフォームごとに呼び出し出すバックエンドのAPIが異なる

最初の実装 (例: WINDOW)

  • 多重継承を多用
  • WINDOW は GENERAL_WINDOW を継承
    • 共通のコードを提供する暫定クラス
    • プラットフォーム非依存
  • WINDOW は PLATFORM_WINDOW も継承
    • プラットフォーム依存の操作
    • 各プラットフォーム毎に別ディレクトリで管理する

問題点

  • 変更の法則に違反しないか?
    • 基本的には問題ないはず
      • 実行環境にプラットフォームは一つなので
    • しかし、PostscriptやHTMLなどのバックエンドに拡張したら問題が起こりそうだ…!
      • 実行環境ごとにプラットフォームが複数できるため
  • より関係のゆるい、顧客関係が望ましいかもしれない

改善案

  • PLATFORM_WINDOW をやめる
  • TOOLKIT 暫定クラスをアダプタとして用意する
    • バックエンドの操作を提供
    • MOTIF/MS_WINDOW などが TOOLKIT を実装
  • WINDOW が各種 TOOLKIT の顧客となる
    • WINDOW → TOOLKIT の参照は handle と呼ぶ

「なるほど、継承の濫用が間違っていたんだな!」

  • …ということではない
  • 事実うまくいっていた
  • 多相的エンティティや動的束縛が使われている

24.4 分類マニア

分類マニアの法則

  • 「すべての後継者は、新しい特性の追加、継承した特性の再宣言、または、不変表明句の追加を行わなければならない

無駄な分類レベルを追加することは自滅行為

  • 親と後継者は、異なる抽象データ型を表していなければならない。

分類マニアが正しいケース

  • 将来に備えるため
  • 覆し用のない根拠がない限りはやるべきではない

例: PERSON と MALE / FEMALE

  • female 属性を用意するのとどちらが良いか?
    • 変種が増えるとあらゆる分岐で修正が発生する
    • 人の性別を識別する必要があるのなら、この説明の前提である、それぞれの変種に固有の特性はない、という事に矛盾する(?)
  • 今回の場合、変種が増えることはない
    • (最近はそうとも言えないような)
  • 分類する基準が途中で増えた場合
    • 複数基準分類(この章で後述)

24.5 継承の使用: 分類学の分類学

規則の範囲

「全ての継承の使用は許されるカテゴリの一つに属さなければならない」

  • 複数のカテゴリは禁止しないが、推奨しない

間違った使い方

  • 「である」関係ではなく単なる「がある」関係
    • CAR_OWNER
  • 区別する必要のある重要な特性が全くない
    • 分類マニアの典型
  • 便宜的継承
    • 他のクラスの特性を再利用するだけのために継承する
    • ただし再利用を否定しているわけではない

大まかな分類

  • モデル継承
  • ソフトウェア継承
  • バリエーション継承

部分型継承

互いに素なサブカテゴリに分類

  • 親クラスは暫定クラスでなければならない

例: VERTEBRATE (脊椎動物)と MAMMAL (哺乳類) など

制約継承

親クラスに不変表明を追加したものをサブクラスにする

  • 双方とも暫定クラスか、双方とも有効でなければならない

例: RECTANGLE → SQUARE

暫定クラスの制約は、他の継承との区別をするためにある

拡張継承

親クラスに適用できない特性を追加する

  • 親クラスは有効クラス

制約継承と一見矛盾する

例: POINT → MOVING_POINT、DOCUMENT → CHAPTER

適切な数学的モデル

  • クラスをモデルするときに、属性の直積で考えない
  • 代わりに、属性→値への部分関数とかんがえる

バリエーション継承

特性の再定義

  • ファンクショナルバリエーション継承と型バリエーション継承がある
  • 親子ともに暫定クラス
  • もしくは親子ともに有効クラスで、かつ以下の条件を満たす場合
    • 再定義で必要としない特性の追加がない

型バリエーション継承

  • 特性のシグネチャだけを変更
  • 型バリエーション継承では like を使うときは不要

ファンクショナルバリエーション継承では、実装方法を変更する

無効化継承

暫定特性への変更

一般的ではないが以下のケースでは使われる

  • 多重継承をで、二つの特性を併合したい場合
  • 親クラスの処理があまりに具体的すぎる場合

具体化継承

暫定クラスの特性の実装

例: TABLE → HASH_TABLE など

構造継承

例: COMPARABLE → NUMERIC

実装継承

共有性質継承

特性のインポート

  • 定数継承
  • マシン継承
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment