|
|
タイプ・クラス・プロトタイプ - OOの語彙その違いは微妙というにはあまりに大きいので、ここでおさらい。 駄文 - JavaScript と「クラス」と「コンストラクタ」と「プロトタイプ」って言葉の定義が難しいよなあ - IT戦記JavaScript関数の実体は、Functionクラスのオブジェクトです。今回はFunctionクラスの機能を網羅的に解説します。 JavaScriptの関数オブジェクトを完璧に理解する - builder by ZDNet Japan「Function クラスのオブジェクト」って言いますよねー。 Type(型)って何?まず、タイプ=型から説明しよう。 型というのは、「どんなデータを、どう置くか」の決まり。例えばCの これは、静的な型(static type)を持つ言語の関数と組み合わせ考えるとわかりやすい。静的な型を持つ言語では、関数というのは、どんな型を持つデータを受け付けるかを「知って」いて、型が合わないとそれを受け付けない。 型がある言語における関数が何かといえば、「自分がどんなデータを受け付けるのかを知っているサブルーチン」ということになる。 Object(オブジェクトって何)?オブジェクトは逆に、データの方が何ができるかを「知って」いる。 オブジェクトとは何か、といえば、「自分が何が出来るのかを知っているデータ」ということになる。 型とオブジェクトの共通点「自分がどんなデータを受け付けるのかを知っているサブルーチン」にしても、「自分が何が出来るのかを知っているデータ」にしても、その目的は、データとプログラムの組み合わせを限定するところにその目的がある。プログラムという「動詞」の方がデータという「名詞」を限定するのが「型」で、データという「名詞」がプログラムという「動詞」を限定するのがオブジェクト、という言い方もできる。 なぜ限定するかといえば、ひとえにプログラマーの脳力を省力するため。データの種類がn個あって、それらを扱うプログラムの種類がm個あったら、可能な組み合わせは、一つのプログラムが一度に扱うデータ(=引数)がたった一つの場合でさえn*m個の組み合わせが考えられるが、「まとも」な組み合わせはそんなにない。 今日日の言語は、どちらの限定法も受け付けるものが多いが、ここからは主にオブジェクトについて話をする。 Class(クラス)はオブジェクトの設計図オブジェクトを作るには、二通りの方法がある。
最初に普及したのが、1のやり方で、設計図はクラスと呼ばれている。クラスはあくまで設計図なのでオブジェクトではない。型がデータそのものでないのと同じように。 Prototype(プロトタイプ)はオブジェクトの母ところが、JavaScriptのおかげで2のやり方が注目されるようになった。すでにオブジェクトがあるなら、それを「コピー」して、違うところだけ後付すればいい。このコピーの元をプロトタイプと言う。母となるオブジェクトから子となるオブジェクトを作るというわけだ。 このやり方でオブジェクトを作る言語を、プロトタイプ型オブジェクト指向言語(prototypal object-oriented language)とかプロトタイプベース(prototype-base OO)と呼んでいる。それと区別する意味で、クラスを元にオブジェクトを作る言語はクラスベース(class-base OO)と呼ぶようになった。
何が決定的に違うかクラスベースのOOとプロトタイプベースのOOで決定的に違うのは、プログラムを動かしている最中にオブジェクトが出来ること、すなわちメソッド(method)を追加したり再定義したりできるかだ。それゆえにクラスベースのOOは静的(static)でプロトタイプベースのOOは動的(dynamic)だ。 どちらにも一長一短はある。オブジェクト指向の目的は、データに出来ることを限定することにある。その点においては、データに出来ることがクラスによって「固定」されているクラスベースの方が安心だ。プロトタイプベースだと、こんなことまで出来てしまう。 var a = new Date; こういう自分の足を撃つような真似、というか「母殺し」は、正直あまり出来て欲しくないものではある。 しかし、限定=固定とは限らないし、変更できるからといって変更する必要もまたない。むしろ「プログラマーの意図どおりに動け」(do what I mean = DWIM)の観点から行けば、データに出来ることがプログラム実行時に変更できた方がありがたいことも多い。例えば if (!Array.prototype.map) Array.prototype.map = function(f){ という具合に、「 動的言語のクラスはプロトタイプ?話がややこしくなるのは、実行時にクラスそのものを改変できる言語もかなり存在することだ。rubyもperlもpythonもそうである。こういった言語では、「クラス」と「プロトタイプ」の境界はかなりあやふやになる。 特にrubyのクラスというのは、クラスであると同時にオブジェクトでもある。そのことは以下を見れば一目瞭然だろう。 irb(main):001:0> 1.object_id rubyのクラスを実行時に改変するのと、プロトタイプを動的に改変するのとの本質的な違いはそれほどないように見える。perlの場合、そもそもOOの仕組みそのものが型ベース(オブジェクトは型の名前を持ち、メソッドはその「型」=名前空間にある関数であり、その関数にはインスタンス(instance)は第一引数として渡される)であるが、任意の名前空間に任意の関数を動的に追加削除できる以上、やはり本質的に異なるとは言いがたい。 まとめ = 「Functionをプロトタイプとするオブジェクト」と呼ぼうこのように、動的言語においてはクラスもまたオブジェクトとして扱えてしまうのではあるが、それでも「プロトタイプベース」と呼ばれないのは、「クラスは改変可能ではあっても理由がなければ改変すべきではない」という不文律が普及しているという理由が一つと、実際のオブジェクトの生成が既存オブジェクトのコピーではなく、オブジェクト生成メソッドの実行(たいてい で、最初の問題提起に戻る。AS3にはすでにclassが導入されているし、将来のJavaScriptにも導入されるようだが(改変不能のオブジェクトして実装?)、しかしFunctionがオブジェクトであり、そこから関数が生成されている以上、やはり「Functionクラスのオブジェクト」とは呼びたくない。呼ぶのであれば「Functionをプロトタイプとするオブジェクト」ないし「Functionから生成されるオブジェクト」ないし「Functionを母に持つオブジェクト」とするべきではないだろうか。 個人的には、最後の呼び方が気に入っている。が、かしこまって言うのであれば最初の例だろう。 Dan the Prototypal Being See Also:
編集部より:今回の記事は,小飼弾氏のブログ404 Blog Not Foundより編集し転載させていただきました。本連載に関するコメントおよびTrackbackは、こちらでも受け付けております。
連載新着記事一覧へ >>著者プロフィールPerl本体の開発チーム・メンバーであり,Perlで日本語を扱うためのモジュールJcode.pm,多言語変換モジュールEncode.pmの開発を手がけたオープンソース・プログラマ。そのほか多くのPerlモジュールを開発しCPANで公開している。元オン・ザ・エッヂ取締役最高技術責任者(CTO)。著書に「達人に学ぶPerl/CGI道場」(インプレス刊)がある。約2万冊の蔵書を持つ重度の活字中毒者としても知られる。「404 Blog Not Found」で社会や技術に対して積極的に発言している。 |