プロトタイプベースの誤解

クラスベースのOOとプロトタイプベースのOOで決定的に違うのは、プログラムを動かしている最中にオブジェクトが出来ること、すなわちメソッド(method)を追加したり再定義したりできるかだ。

404 Blog Not Found:タイプ・クラス・プロトタイプ - OOの語彙


これはひどい。w オブジェクトに対して動的(実行時)にメソッドやインスタンス変数を追加できることと、“プロトタイプベース”においてオブジェクトがそれが属するクラスによらず独自のメソッドやインスタンス変数を持てることとは別の話です。


あらためて、「プロトタイプベース」という用語自体に問題が多いことを実感させられる記事でもありますね。個人的には、クラスを用いないオブジェクト生成手法の話でないのならば(つまり、「プロトタイプの複製でオブジェクトを生成する」ことが話の本筋でないならば)「プロトタイプベース」ではなく、「インスタンスベース」(あるいは「オブジェクトベース」…)と言い換えることを推奨しています。最近は説明が面倒で「プロトタイプベース」で通してしまうことも多いのですが…反省。

#ちなみに「インスタンスベース」や「オブジェクトベース」というのは、別に私の造語というわけではなく、論文や書籍などで比較的古くから使われている用語です。


繰り返しになりますが念のため。オブジェクトがそれが属するクラスによらず独自のメソッドやインスタンス変数を持てること*こそ*が、「プロトタイプベース」あらため「インスタンスベース」の本質です。


「プロトタイプベース」というと(それを世に広めた SELF の影響で)「クラスがない」と短絡する人が多いのも問題のひとつです。そうした偏った思いこみを払拭するのにも「インスタンスベース」との言い換えは有効だと思います。オブジェクトが独自のスロットを持てることと、そのオブジェクトがクラスに属することは矛盾しない、つまりインスタンスベースの言語でもクラスを持つことはできるし、逆に、クラスベース言語でも(その言語がクラスベースにおいて純粋さを目指さない限りにおいて…)そのオブジェクトにインスタンスベース的素養を持たせることは可能です。

実際、完全なインスタンスベースの言語(NewtonScript、JavaScriptActionScript)にクラスがあってもまったく問題はないわけですし、クラスベースの言語(RubyPython)であっても、オブジェクトがインスタンスベース的素養を持つ例はめずらしくありません。

ちなみに、Rubyインスタンスベース的側面として取りあげられることが多い「特異メソッド」(インスタンス特異的メソッド)ですが、実はこの機能、無名で通常は不可視の「特異クラス」(インスタンス特異的クラス)を介して実現されています。そもそもメソッドの扱いに限っては、Smalltalk 同様、きわめてお堅いクラスベースの言語である Ruby では、「特異メソッド」を(インスタンスベースの言語でなら通常そうするように…)オブジェクトへのスロットの追加というかたちで表現できないため、こうした苦肉の策がとられているわけです。面白いですね。


なお、「プロトタイプベース」においてその名が示す「プロトタイプの複製でオブジェクトを生成する」という特徴は、(クラスが必須のクラスベースでは、クラスを new できるのに対し)インスタンスベースでクラスがないときに使われるオブジェクト生成のバリエーションのひとつ…という程度の位置づけにすぎず、そうでなければならないという類のものではありません。


このオブジェクト生成にからめた「プロトタイプベース」関連の用語としては、「プロトタイプとクローン(コピー)」、「ペアレントとチャイルド」という用語やそれぞれの関係も混乱の元になりがちですね。これらも、オリジナルとその浅いコピーの関係なら「プロトタイプとクローン」、委譲先としての情報を持つだけなら「ペアレントとチャイルド」と統一してはどうかと個人的には思うのですが、現状、ペアレント(移譲先の)スロットを「プロトタイプ」やそれに準ずる呼称とする言語が多い(関連して「プロトタイプ・チェーン」なんて言葉があるくらいですし…)ので、難しいですね。

もしこの提案を受け入れてもらえるなら、インスタンスベース的視点において、ネタ元のオブジェクトの呼び名は「Function.prototype をペアレントとするオブジェクト」あるいは「Function.prototype のチャイルド」というのがふさわしいということにできて一件落着なのですが、なかなかそういうわけにもいかないでしょう。であれば、「Function.prototype を移譲先に持つオブジェクト」…かしらん(とはいえ、.prototype がうざいね汗)。