檜山正幸のキマイラ飼育記 このページをアンテナに追加 RSSフィード

キマイラ・サイトは http://www.chimaira.org/です。
トラックバック/コメントは日付を気にせずにどうぞ。
連絡は hiyama{at}chimaira{dot}org へ。
蒸し返し歓迎!
ところで、アーカイブってけっこう便利ですよ。タクソノミーも作成中。

2006-06-27 (火)

クラス、オブジェクト、型; なんだか変じゃない?

| 10:28 | クラス、オブジェクト、型; なんだか変じゃない?を含むブックマーク

「オブジェクト指向と得体の知れないモノたち」の続きみたいなハナシ。クラスやオブジェクトをなるべく“ドライに考える”ための練習。クイズだと思っても、実務的ヒントとして受け取っても、どっちでもいいですよ。

この継承は変な感じ

class Point2D {
 protected double x;
 protected double y;

 // コンストラクタ(略)

 void moveTo(double x, double y) {
  // ...
 }
 // ... 点を操作するいろいろなメソッド
}

class ColoredPoint2D extends Point2D {
 protected Color color;

 // コンストラクタ(略)

 Color getColor() {
  return color;
 }
 // ...
}

class Point3D extends Point2D {
 protected double z;

 // コンストラクタ(略)

 // ...
}

ColoredPoint2D extends Point2Dはいいのだけど、Point3D extends Point2Dは気持ち悪いんだけど、何故でしょう。([追記]typo直した。[/追記]

こういう型をクラスで定義したいのだけど

  1. ASCII文字だけからなる文字列 AsciiString
  2. 非負の整数 NonNegativeInteger
  3. テストの点数として0から100までの整数 Score100
  4. 同様に0から1000までの整数 Score1000

JavaのStringやIntegerは継承できませんが、仮に継承できたとして、class AsciiString extends Stringとかclass NonNegativeInteger extends Integerとしてうまく定義できるのでしょうか?

テストの点数は列挙型でなんとかなりそうですが、0点から1000点まで並べる? 10000点までならどうする?

こういう型達の関係は

会員番号もハンドル(ニックネーム)も、どっちでもユーザーIDとして使えるとします。

class UserID {
 protected int number;
 protected String handle;
 // ...
}

numberとhandleの両方が同時にセットされることはないことを保証したいのですけど、どうしましょう?

さらに、UserNumberとUserHandleというクラスがあるとして、UserID, UserNumber, UserHandleの間の継承関係はどうしましょうか。

どっちに味方しますか

TextViewerは、その名の通りテキスト閲覧機能を提供するコンポネントのクラスです。TextEditorは編集も可能なクラスです。AさんとBさんの主張が食い違ってます。

  • Aさん:TextEditor extends TextViewerとすべき。
  • Bさん:TextViewer extends TextEditorとすべき。

Aさん「TextViewerに、編集機能を実現するコードを追加してTextEditorを実装するよね。だから、TextEditorがサブクラスに決まってるでしょ。」
Bさん「いや、汎用のTextEditorをまず作っておいて、それを他で利用するんだ。サブクラスであるTextViewerでキーボートイベントのハンドラをdo-nothingにオーバライドするだけでOK」
Aさん「サブクラスで編集機能を追加するんだ!」
Bさん「サブクラスで編集機能をつぶすんだ!」

石川直太石川直太 2006/06/27 16:05 Aさん:実数に虚数部を追加したものが複素数である。
Bさん:複素数の虚数部が0の特別な場合が実数である。
Aさん:8086に機能を追加したものが386である。
Bさん:386の16ビットモードが8086である。
うーむ。私は、機能を少しずつ追加していく方法でしばしば開発しますが、基本設計が悪かった場合の泥沼が怖いです。

通りすがり通りすがり 2006/06/27 22:30 Aさん:三角形に1点加えたものが四角形である
Bさん:五角形から1点とり除いたものが四角形である

無色透明の物体を識別できない身としては
ColoredPoint2D extends Point2D も気持ち悪いですね。

m-hiyamam-hiyama 2006/06/28 10:02 石川直太さん、通りすがりさん、
Aさん/Bさんシリーズ、ってか。

t_tradt_trad 2006/06/29 11:01 つまり、Aさんの考えるルートクラスは「何の機能も実装されていない」クラス、Bさんの考えるルートクラスは「あらゆる機能が実装されている」クラスということですね。
……うーん、”ドライ”に考えられなくなってきた。

m-hiyamam-hiyama 2006/06/29 11:26 t_tradさん、
> ”ドライ”に考えられなくなってきた。
僕もドライに考えられなくなってきました。すべての根源である神は空虚なんでしょうか、それとも万能なんでしょうか?

通りすがり通りすがり 2006/06/29 23:54 上の通りすがりですが、

機能指向、実装指向な分析/設計とOOD/OOPを無理矢理結びつけるから変になるんだと思います。

ということで、Cさん登場 :)

Cさん: オブジェクト指向分析をしろ (機能指向や実装指向でなくて)。話はそれからだ。」

bonotakebonotake 2006/07/01 08:20 AsciiStringとStringの区分けが「機能指向」だとも思いませんけども。(そもそも機能指向って何よ、という話もありますが)
無理に継承を使うな(継承関係を使って表現するのが適切でない)と言う話なら分からなくもないですが、じゃあ逆に、継承ってどう使えばいいの?という問いかけをすれば元の問題に戻っていく気がします。


ということで、そろそろこの人も登場させますか。

客「グダグダ言ってないで、なんでもいいからさっさと作れよ!>all」

m-hiyamam-hiyama 2006/07/01 10:07 通りすがりさん、bonotakeさん、
まー、いずれにしても登場人物が増えるとハナシがややこしくなりますな。

hirohiro 2006/07/06 16:51 Score100 --> [0..100] (Pascal)

SiroKuroSiroKuro 2006/07/07 00:01 TextViewer extends TextEditor は、リスコフの置換原則が成り立たないような気がするのですが……。TextEditor を利用したいのならば、TextViewer has-a TextEditor にするのが良いかと思います。

m-hiyamam-hiyama 2006/07/07 11:02 hiroさん、SiroKuroさん、
→ http://d.hatena.ne.jp/m-hiyama/20060707/1152237579