Self
Self の特徴の1つとして、Smalltalk システムが使っていた仮想機械と同様の仕組みに基づいている点が挙げられる。つまり、Self のプログラムはC言語などとは異なり、それ単独では機能しない。常に実行環境が必要となる。しかし、このようになっているため、Self 環境は強力なデバッグツールを提供できる。プログラムを任意の時点で停止させ、コードや値を変更し、実行を再開させるといったことが可能である。
さらに、Self 環境はオブジェクトを素早くかつ継続的に変更することを考慮している。「クラス」設計のリファクタリングは、単に既存のメソッドを新しいオブジェクトに引っ張ってくればよいだけである。メソッドの評価のような単純な作業は、コピーを作って、メソッドをコピーに引っ張ってきて、そこで修正すればよい。他のシステムとは異なり、その新たなオブジェクトだけが新しいコードを持っており、テストするにも他に影響が発生しない。そのメソッドがうまく動いたら、それを元のオブジェクトに戻せばよい。
Self のオブジェクトは「スロット」の集まりである。スロットとは、値を返すメッセージであり、スロット名の後にコロンをつければ値をセットするメッセージになる。例えば、"name" というスロットがあるとする。
これは name の値を返す。
これは値をセットする。
Self は Smalltalk と同様「ブロック」を使って処理の流れを制御する。メッセージを受け取るメソッドはスロット群以外にコードを持つオブジェクトであり、任意のスロットの値としてメソッドを格納できる。メソッドの持つスロットは引数や一時変数として使われる。いずれの場合も文法的には同じである。
Self ではフィールドとメソッドに区別はなく、どちらもスロットである。メッセージによるスロットアクセスで Self の文法の大部分が説明されるため、自分自身(self)へのメッセージも多い。そのため "self" は省略できる(また、これが言語名の由来)。
receiver slot_name
"<-" という記号は、第一のスロットの値を変更するのに使われる 'vehicle:' という第二のスロットを暗に示している。
"=" は定数スロットを意味するので、'parent*' には対応する 'parent:' が無い。このリテラルオブジェクトは 'vehicle' の初期値であり、クローン作成に関するメッセージを理解できるスロットを1つもっている。完全に空のオブジェクトは、(| |) あるいは単に () で示され、メッセージを全く受け付けられない。
これも、前と同じオブジェクトが受信者であり、'parent*' に加えて新たに 'name' と 'name:' スロットが追加されている。
以前の 'vehicle' と 'sportsCar' はほとんど同じだが、ここでは後者にオリジナルが持っていなかったメソッドを伴うスロットが含まれている。メソッドを持つことができるスロットは定数スロットだけである。
新たなオブジェクト 'porsche911' は 'sportsCar' とほぼ同じだが、最後のメッセージでその 'name' スロットの値が変更されている。これらはスロットの値は異なるものの、持っているスロットは同じであることに注意されたい。
もう少し複雑な例として次の記述を示す:
"labelWidget" オブジェクトへの copy メッセージでコピーを作り、そのコピーの "label" スロットに "Hello, World" メッセージを格納すべくメッセージを送っている。これを使ってみると次のようになる。
この場合、(desktop activeWindow) が最初に評価され、desktop オブジェクトが知っているウィンドウのリストからアクティブウィンドウを表すオブジェクトが返される。次に(内側から外側へ、左から右へという順で)前掲のコードが評価され labelWidget が返される。最後にそのウィジェットがアクティブウィンドウの draw スロットに送られる。
Self のガベージコレクションは世代型であり、オブジェクトを世代で管理する。メモリ管理システムを使ってページへの書き込みを記録し、ライトバリアを保つ。この手法は性能がよいが、ある期間実行を行っていると全体ガベージコレクションが発生し、無視できない時間を取られてしまう。
Self のオブジェクトにはスロットを追加可能である。グラフィカルなプログラミング環境でもできるし、'_AddSlots:' プリミティブでも可能である。プリミティブは通常のキーワードメッセージと同様の構文だが、その名前は常にアンダースコアで始まる。_AddSlots プリミティブ自身は古い実装の名残りであるため、使うべきでないとされている。しかし、これを使うとコードを短縮できるため、以下ではあえて解説する。
Vehicle という単純なクラスのリファクタリングで乗用車とトラックで振る舞いを変えることを上の例で示した。Self ではこれを次のように実現できる:
'_AddSlots' プリミティブの受信者オブジェクトが明示されていないので、これは "self" に対するものである。これを対話型のプロンプトで入力すると、"self" オブジェクトに相当するのは "lobby" と呼ばれるオブジェクトである。'_AddSlots' の引数はオブジェクトであり、そのスロットが受信者オブジェクトにコピーされる。この例では、それは1つのスロットだけを持つリテラルオブジェクトである。スロット名は 'vehicle' で、その値が別のリテラルオブジェクトとなっている。