まつもと ゆきひろです

In message "[ruby-list:6314] RE: ruby's design policy (Re: I'd like to subscr ibe this ML)"
    on 98/02/06, 助田 雅紀 <masaki.suketa / tonen.co.jp> writes:

|私には、ruby の Mix-in と C++ なんかの多重継承の違いがはっきり
|しないです。考えれば考えるほど、多重継承とほとんど変わら
|んのじゃないかと思えてしまうんです。

そうなんですか.じゃあ,まずその前提になる

|後、変数が型にしばられない(という言い方でわかります?)設計
|にしたのは何故かとか。

について先にお話しましょう.プログラミング言語の型システムを
考える中で大きくわけると3つあります.

  Static Typing(静的型)

    PascalやC++など「変数に型がある」タイプの言語です.この
    タイプのメリットはコンパイル時に型の不整合のチェックが出
    来るので,型にまつわるトラブルを早期に発見できる(ことが
    多い)ということです.もっとも,C++などは型システムが穴だ
    らけなので,型関連のバグを全て検出できるわけではないので
    すが.

    あと,オブジェクト指向言語という観点から静的型システムを
    見ると,ちゃんとした(問題を検出できる)型システムであるた
    めにはコンテナ型を表現するための型演算が必要になります.
    一番有名なのはC++のtemplateです.これがないと一度void*の
    ような汎用の型に変換して,さらに必要に応じてまたもとの型
    に戻す,ということが必要になります.この「元の型に戻す
    (downcast)」というのは型システムに穴を開ける大変危険な行
    為です.

  Dynamic Typing(動的型)

    変数には型が無く,オブジェクトに型があるというrubyのよう
    な型システムです.このような型システムはlispにはじまり,
    インタプリタ的なシステムで広く用いられています.オブジェ
    クト指向言語でもSmalltalkをはじめ,広い範囲で採用されて
    います.もっとも,最近はC++のような静的言語がはやりのよ
    うですが.

    このシステムの利点はまず手軽さです.スクリプト系の手軽な
    プログラムを作る場合に型について悩まずにすいすいプログラ
    ムが書けます.それから柔軟性もあります.引数がある型に適
    合しているかどうか保証する必要はなく,ただあるメッセージ
    に反応するかどうかだけで適合が決まるので,不自然な継承関
    係を作る必要はありません.また,上述のdowncastのような問
    題も発生しません.また,コンパイル時の型解析の必要が無い
    ので処理系がコンパクトになるというメリットも重要です.

    逆に欠点は型の不整合の問題が実行してみないと分からないこ
    とです.更に型チェックが動的に行われるため実行コストがか
    かる場合もあります.

  Typeless(型なし)

    PerlやAWKなど「状況に応じて適当にデータが変換される」タ
    イプの型システムがこれにあたります.もっとも,本当に型の
    無いシステムってのはBCPLとかアセンブラくらいで,Perlも
    AWKもなんとなく動的型に近い部分を持ってます.

    これはもっとも柔軟ですが,「型に操作が付随する」オブジェ
    クト指向とは相い入れません.

# 昔は「静的型ってなに?」って感じだったんですが,最近はC++
# が広まったせいか,動的型について説明しないといけなくなって
# ますね.

|Java は、逆に Interface 使って、単一継承だけでは使いにくい部分
|をカバーしていると思うんですが、このインターフェースの継承(と
|いう言い方が適切かどうか自信ないですが)を採用しないで実装の
|継承を採用した理由とか知りたいです。

あるオブジェクトを使う時重要なのは「どのようなメソッドに反応
するか」ということで,これをそのオブジェクトの「仕様」と呼び
ます.静的型の言語の場合,そのオブジェクトが格納されている変
数(あるいは式)の型が「仕様」を表現しています.「仕様の継承」
とは「このクラスのインスタンスはこのスーパークラスのインスタ
ンスだと思って操作してもちゃんと動作するよ」という意味です.

また,そのオブジェクトのクラスを定義する場合にはすでに存在す
るクラスの構造やそれに依存したメソッド定義を流用したくなりま
すが,それらは「実装の継承」と呼ばれます.これは「このクラス
を作る時に,このスーパークラスの構造とメソッドを借りて来たよ
(んで,必要に応じて再定義したよ)」という意味です.

さて,静的型言語における式の型あるいは変数の型で表現される仕
様ですが,これはほとんどの場合木構造では表現できません.です
から,静的型のある言語がちゃんとした型システムを提供しようと
思えば,多重継承を導入するか,Javaのようにinterfaceを経由し
て,仕様を共有するしかありません.

ところが一方,動的型言語では仕様というのはある意味存在しない
(正確に言えばプログラム中でオブジェクトに対してどんなメソッ
ドを呼び出しているかで決まる)ので,そもそも仕様の共有を行う
必要がありません.ですから,仕様の継承と言う観点からは多重継
承もinterfaceのような仕組みも必要ないわけです.

動的型言語では「仕様の共有」の必要が無いことは既に述べました.
となると後は実装の共有ことだけを考えれば良いわけですが,ここ
で単純さあるいは理解しやすさから,単一継承を選ぶとJavaのよう
に「実装の共有はあきらめる.必要に応じてコピーする」か,Ruby
のように「Mix-inを採用する」かどちらかになるのではないでしょ
うか.Rubyはエラーの発生しやすいコピーを避けて(コピーの方を
修正し忘れたりするし),Mix-inを採用したということです.

んで,最初に戻って

|私には、ruby の Mix-in と C++ なんかの多重継承の違いがはっきり
|しないです。考えれば考えるほど、多重継承とほとんど変わら
|んのじゃないかと思えてしまうんです。

ということになると,そんなに違いはないです.Mix-inはもともと
多重継承の使い方のテクニックとして発生した考えですから,多重
継承があれば実現できちゃいますから.ただ,rubyの場合Min-inが
強制されていることによって,継承関係が複雑になることを言語レ
ベルである程度排除しているといえます.

# これは「自由が信条」のrubyの他の部分とは異なるポリシーです
# が,作者がこのアイディアにそれだけこだわっている証拠ですね.

|で、この辺のことが、ruby 本で解説されていると嬉しいです。

# 説明しちゃいました.^^;;;
えーと手元の原稿を見ると1章である程度解説されてますね.まだ
書いてない4章にも登場するかも.

                                まつもと ゆきひろ /:|)