オブジェクト指向言語として必須な要素とは何か?


ときどきの雑記帖 リターンズ -おしえて(OOPLの)えらいひと より。お呼びでない…とは思いましたが、私のこれまで調べたことを頭の中で整理するのに役立ちそうなので、できるだけ簡潔にまとめてみます。


ケイのオブジェクト指向(メッセージングのオブジェクト指向)に立脚する場合

このオブジェクト指向のコンセプト

パーソナルコンピューティングに係わるものをメッセージングで表現。

それをサポートする言語に必須のもの

メッセージング(あるいは、それに準ずる)機構と、メッセージのレシーバ(たいていは、オブジェクト。状態や処理の保持・保護・隠蔽を行なえることが期待される)。

原則として欠いてはいけない機能

可能な限りの動的性。

ストラウストラップのオブジェクト指向(ユーザー定義型のオブジェクト指向)に立脚する場合

このオブジェクト指向のコンセプト

抽象データ型(この文脈ではユーザー定義型を指す)を「クラス」を使って定義。

それをサポートする言語に必須のもの

クラス(と、もちろん、それにより定義した「型」に属するデータ。すなわちインスタンスとしてのオブジェクト)。

原則として欠いてはいけない機能

抽象データ型をサポートする機能(ユーザーがデータ型を定義できる機構)、継承(多重継承)、仮想関数などによる動的性、静的型チェック、アクセスコントロール情報隠蔽)。(最初の三つは、俗に言う「カプセル化・継承・多態性」のこと)

クックのオブジェクト指向(手続きによる抽象化手法)に立脚する場合

このオブジェクト指向のコンセプト

データに持たせる「手続き」によるデータ抽象化手法を「オブジェクト指向」と定義する。なお、対極に「抽象データ型」(ただし、この文脈で「抽象データ型」は、データに持たせる「型」による抽象化手法を指す)

それをサポートする言語に必須のもの

データ型を定義できる機構。たいていは、クラス(と、それにより定義した「型」に属するデータ)。

原則として欠いてはいけない機能

手続きによるデータ抽象化をサポートする機能。たいていはクラスに従属する関数(メンバ関数、メソッド)を定義する機能。


以上をふまえると、Perl のオブジェクトシステムは、ずばり、「型」によらない、「手続きによるデータ抽象化手法」をとっている(追記:これは「型」がないという意味ではなく、端的には「型」ごとに必要な「手続き」を持っている…ということ)ので、Perl は、クックのオブジェクト指向でなら胸を張って OOPL を名乗れそうです。しかし残念ながら他の二者、「ケイの…」「ストラウストラップの…」のいずれかに立脚する場合、Perl のオブジェクトシステムは、それぞれに原則として必須とされる要素や概念を欠いているので、厳格な人には Perl を OOPL と見るには足りていないと感じるでしょう。もちろん、独自の「オブジェクト指向」をあみ出した人や、そうでなくともとてもおおらかな人(たとえば、「ケイの…」であれば、関数のコールを「メッセージング」だと“読み替え”ることに抵抗のない人、「ストラウストラップの…」であれば、静的型チェック・アクセスコントロールなどの欠落に頓着しない人)は、Perl を紛れもない OOPL だと主張することでしょう。

一方、CLOS は、どの「オブジェクト指向」においてもその要素を満たしていません(足りていない and/or “斜め上”を行っているからそもそも必要ない…かは別にして)。しかし、Perl 同様、いや、Perl より強烈な印象として、CLOS の設計者は、上記三者には属さない、独自の「オブジェクト指向」(あるいはそれを超越した考え方)に立脚していると考えるほうが自然に思えます。


ここで注意していただきたいこととして、それぞれの「オブジェクト指向」の提唱者が設計した Smalltalk にしても、C++(特に初期のものについては)にしても、必ずしもその設計者が提唱している「オブジェクト指向」を完全にサポートできてはいないということがあります。言語仕様やその実装から「概念」を学ぶのことが困難で、間違った結論に至ってしまう危険性があることを常に意識すべきです。逆に、ユーザーがそれぞれの「概念」や「方法論」を会得できてさえいれば、「ストラウストラップの…」を Smalltalk にサポートさせることも、「ケイの…」を C++ にサポートさせることも、限定的ではあれ、不可能ではないでしょう。大事なのは「概念」で、言語はそれをサポートするために作られたツールに過ぎない…というわけです。ですから、自分の気に入っている Hoge 言語は OOPL か否か、と気にするよりは(ここでは話の流れ上、そうした書き方をしてしまっていますが…)、その言語がどんな「オブジェクト指向」をサポートするのに適しているのか…と考えるようにしたほうがよいと思います。



元ネタに戻ります。個人的には、言語でオブジェクトシステムが“後付け”であることのメリットは、表現力に決定的に劣る言語でない限り and/or 限定的であることを許容しさえすれば、理屈のうえではいかなる「オブジェクト指向」に立脚したシステムをも構築できること…だと考えます。同時にデメリットは、自分自身を変化させる能力 and/or 究極の動的性を有する特殊な言語(当然、Smalltalk を意識しています…w)でない限り、後付けのオブジェクトシステムという“部分”をもって言語処理系という“全体”に変化を行き渡らせることは難しい…ということではないかな、と。


この切り口において、LISPerがしきりに強調するマクロの優位性は、LISP 自身の根幹に手を入れることなしに、“部分”を“全体”に行き渡らせることが可能であるかのように見せる(後付けであるという印象を払拭できないまでも薄められる…)演出がマクロにより容易になる…と解釈できるのではないでしょうか。


他方ですでに前振りの通り、我らが SmalltalkSmalltalk-76 以降、マクロ的な機能を排除する判断をあえて下した…)においては、自身を自身で記述している(記述「可能」なのではなく、実際に記述したもので普通に運用されている)…という、LISP を含む追記:shiro さんからのご指摘で LISP も一部の例外を除き自身を自身で記述したもので運用するのが常だそうです。追々記:訊けば Java も自身で記述されているようですから、もうこの主張はガタガタですね(^_^;)。以下は自戒のため削除せず晒しておきます…)他の一般的な言語にはない特殊な状況下に常に自らを置くことで、いざとなれば(メッセージングのシンパとしては、その必要が生じないことを強く望みますが(^_^;))新しいオブジェクトシステムへの段階的な全面移行も可能であることを強調…すると叩かれそうなので少し控えめに主張(弱っ!)…しておきたいと思います(もっとも、そんなふうに異質なオブジェクトシステムへと変貌を遂げてしまった Smalltalk は、もはや「Smalltalk」ではないような気もします…が)。