昨日のエントリー「クラス、オブジェクト、型; なんだか変じゃない?」にトラックバックをいただきました。
([追記]ここにもありましたよ、設問への答えが→http://return0.dyndns.org/d/2006/06/27#s1 。「Python なら対応できるのに。」 -- どうやるんだろう? それと、「出題者の期待している答え」は特にありません。[/追記])
いずれも、僕の意図をご理解いただいての反応なので、以下、アラズモガナな補足ですが:
「練習」「クイズ」という言葉を使いましたが、これは正解や模範解答があるようなシロモノではありません。いろいろな立場からいろいろに考えたり話し合ってくださればいいかと。そのネタを提供したつもりです。
まー、クラスと継承にこだわっても、あんまりうまくいかない事態もあるんじゃないの? と、思いついた(作為的)事例を並べてみたんですよ。「あんまりうまくいかない」とは:
- 概念的になんか不自然。
- 作業負担が軽減されない、退屈なコーディングになる。
- 型階層と継承階層が一致しない(不整合)でトラブルのもと。
- 不毛な議論をまねく。
など。
あとそれと、「こういう型をクラスで定義したいのだけど」のところでは、AsciiStringだけじゃなくて、AsciiStringBufferも一緒に考えてください。Javaだと、そもそも継承ができないので、一般的な状況として次を考えて欲しいのです。
- 文字列(変更不可能と変更可能)、整数(いろいろな演算や比較ができる)がクラスとして既に定義されているとき、それを継承して、ASCII文字だけを扱うクラスや非負整数だけを扱うクラスを上手に定義できるか?
bonotakeさん、sawatさんが触れているのですが、オブジェクト指向言語だと(例外もあるでしょうが)、ユニオン型(バリアント型)、部分集合の型(条件で値の領域を制限して作る型)を定義するのは苦手なようです。これは、B is-subtype-of A の背後にある領域間対応が、B→Aという射影(projection)であり、埋め込み(embedding, injection)ではないことが原因だろうと思います。つまり、埋め込みが苦手ってこと; AとBのユニオンは、(値の領域としては)AとBの直和 A+B でモデル化されます。直和の入射 A→A+B、B→A+B は埋め込みです。B⊆Aのとき、自然包含写像(natural inclusion)B→Aも当然に埋め込みです。
おおざっぱにまとめれば、(多くの)オブジェクト指向言語の型階層は射影ベースであり、埋め込みベースの型階層を表現しにくい、ってことでしょう。他の論点もいろいろとあるでしょうけどね。