多くのプログラミング言語におけるオブジェクト指向は、オブジェクトの生成に際し、 クラスを定義し、そのインスタンスを生成するという形をとります。 これを、クラスベース・オブジェクト指向と呼びます。 これに対し、Cyan におけるオブジェクト指向では、 クラスという概念を用いずともオブジェクトを生成できます。 これが、Cyan のインスタンスベース・オブジェクト指向です。
Cyan におけるオブジェクトは、 スロット、メッセージ、 ペアレントへの委譲という三つの概念を持ちます。 スロットとは、クラスベースにおけるフィールドとメソッドの両方を担います。 アクセスに制限はありません。次のようにしてアクセスします。
# オブジェクト human のスロット name へのアクセス human.name |
また、スロットには関数をセットすることができ、これをメソッドとして呼び出せます。 メソッドを呼び出すには、メッセージを引数と共に送ります。
# human に対して walk というメッセージを "east" という引数と共に送る。 human.walk("east") |
メッセージを受け取ったオブジェクトは、 自身にメッセージと同名のスロットがある場合、 そこにセットされた関数を呼び出します。 その際、メッセージと共に受け取った引数に、第一引数として自身を追加し、 それを引数とします。
しかし、自身にメッセージと同名のスロットが見つからない場合、 parent というスロットにセットされたオブジェクトにそのメッセージを送ります。 このオブジェクトをペアレントと呼び、この動作をペアレントへの委譲と呼びます。 逆に、あるオブジェクトに対し、それをペアレントとするオブジェクトのことを チャイルドと呼びます。
ちなみに、スロットへのアクセスにおいても、自身にスロットが見つからない場合 ペアレントのスロットを探します。
ペアレントは、クラスベースにおけるクラスとして使用することができます。 また、ペアレントのペアレントを設定すれば、クラスの継承を実現できます。 つまり、ペアレントとチャイルドの関係は、 クラスとインスタンス、スーパークラスとサブクラスの関係を内包します。
これらを踏まえて、実際にコードを書いてみましょう。 ちなみに、Cyan のオブジェクトはペアレントをたどっていくと、 必ず Object というオブジェクトに行き着きます。 Object には基本的なメソッドが定義されており、 その1つが自身のチャイルドを作成する child メソッドです。
Human = Object.child() Human.walk = ^(self, dir){ say(self.name + " walked " + dir + ".") } Superman = Human.child() Superman.fly = ^(self, dir){ say(self.name + " flew " + dir + ".") } human = Human.child() human.name = "John" human.walk("east") #=> John walked east. superman = Superman.child() superman.name = "Clark" superman.fly("north") #=> Clark flew north. superman.walk("west") #=> Clark walked west. |
Human である John は歩くことしかできませんが、 Superman である Clark は飛ぶことができます。 もちろん、Clark は歩くこともできます。
上記のコードにおいて、^(self, dir){ .. } という記述がありますが、 これは無名関数です。ここでは簡単にするため、 インデントブロックや method 関数、 self の省略などを使っていませんが、 これらを使えばもっとスマートに記述することができます。 また、say(..) というのは、標準出力に引数として渡されたオブジェクトを表示する 関数 say の呼び出しです。
インスタンスベースの利点は、オブジェクトに対して、 動的にメソッドの追加・変更ができることです。 その際、オブジェクトがクラスであっても構いません。 また、スロット parent の内容を変更すれば、ペアレントも動的に変えられます。 これにより、コードの可能性が広がります。
さらに、先ほど式とオブジェクトの項で述べたように、 Cyan の抽象構文木はファーストクラスのオブジェクトですから、 スロットの編集によってコードを編集できるわけです。
ちなみに、Cyanで言うインスタンスベース・オブジェクト指向は、 プロトタイプベース・オブジェクト指向言語(特に Io)における プロトタイプをペアレント、クローンをチャイルドと言い換えたものとして用いています。