「オブジェクト指向」と聞くと、まず設計図となる「クラス」を書くところから始まる、と考える人が多いのではないでしょうか。ところが、世の中には クラスという概念そのものを持たない オブジェクト指向言語があります。それが今回紹介する Self です。
設計図を用意する代わりに、すでにあるオブジェクトを複製して使う――この「プロトタイプベース」という考え方は、いまや JavaScript を通じて誰もが日常的に触れているものです。この記事では、Self がどんな言語だったのか、そしてなぜ言語そのものより実行時最適化の技術のほうが後世に強く残ったのかを解説します。
1. Self とは何か
Self は 1986 年に Xerox PARC で David Ungar と Randall Smith により設計が始まった、Smalltalk の方言として出発した研究用言語です。最初の公開は 1990 年で、翌年には開発チームが Sun Microsystems へ移籍し、その後も version 4.0(1995 年ごろに開発が一段落)、version 4.3(2006 年)と続き、現行版は 2024 年 8 月リリースの Self 2024.1 です。
言語仕様は OOPSLA 1987 の論文 “Self: The Power of Simplicity”(David Ungar, Randall B. Smith 著)で発表されました。ちなみに言語名は、メソッド内で自分自身を指す self の記述を省略できる特性に由来する、と Wikipedia では説明されています。
2. スロットという統一概念
Self の最大の特徴は、 変数もメソッドも「スロット」という同じ仕組みで扱う ことです。動画で紹介されたコード例を見てみましょう。
'here is some code' printLine
( | x <- 3 + 4. y <- 5. | )
1行目は文字列オブジェクトに printLine というメッセージを送っているだけの、シンプルな出力コードです。2行目はオブジェクトの定義で、縦棒 | | の中にスロットを並べます。
Self Handbook の言語リファレンスによれば、<- は書き換え可能なスロット(データスロットと、それに対応する代入用スロットの組)を作り、= は式を評価した結果を格納する読み取り専用スロットを作ります。このほかにも継承関係を表す親スロット(名前の末尾に *)や、メッセージの引数を受け取る引数スロット(名前の先頭に :)があり、Self ではオブジェクトの状態も振る舞いも、すべて同じ「スロット」という単位で統一的に表現されます。
3. クラスの無いオブジェクト指向、プロトタイプベースとは
一般的なオブジェクト指向言語では、まずクラスという設計図を書き、そこから個々のオブジェクト(インスタンス)を生成します。一方 Self には最初からクラスが存在せず、既存のオブジェクトを複製(クローン)し、必要な部分だけ書き換えて使います。これが「プロトタイプベース」と呼ばれる方式です。
Self Handbook の説明でも、メソッドは実行時に暗黙の親スロット self を伴って複製され、新しい活性化オブジェクトが作られる、という仕組みが述べられており、オブジェクトの複製を軸に据えた設計思想がうかがえます。この考え方は、いまの JavaScript のプロトタイプチェーンにも通じるものです。実際 Wikipedia の記述でも、Self が影響を与えた言語として NewtonScript や JavaScript が挙げられています。
4. 本当の遺産は言語ではなく実行時最適化技術
Self 自体は研究用言語として広く普及したわけではありませんが、動画でも語られているとおり「実行しながら最適化する」技術が後の世代に受け継がれました。動的型付けで抽象度の高いオブジェクト指向言語を、最適化された C 言語の半分程度の速度で動かすために、Self の研究では複数の Just-In-Time コンパイル技術が生み出され、改良されていきました。Wikipedia の記述では、これらの JIT 技術が Java の HotSpot 仮想マシンに採用されたとされています。
いまの JavaScript エンジンについても、動画では「先行例とされる」という控えめな表現で紹介されています。実際、V8 などの現代的な JavaScript エンジンは、オブジェクトの形状(shape)ごとに最適化されたアクセスパスを作る「インラインキャッシュ」に類する技術を使っており、これは Self の研究がルーツの一つとされる考え方です。ただし個々のエンジンの実装が Self の成果をどこまで直接引き継いでいるかは資料によって濃淡があるため、断定はせず「先行例」「ルーツの一つ」といった位置づけにとどめておくのが誠実です。
5. 手元で動かす
Self は今も開発が続いており、GitHub の russellallen/self リポジトリがメインの開発拠点です。リポジトリの説明文は “Making the world safe for objects”。Issue や Pull Request のやり取りも続いており、決して過去の遺物として放置されているわけではありません。
すぐに試したい場合は、公式サイトで配布されている Linux / NetBSD / FreeBSD 向けのビルド済みバイナリを使うのが手軽です。ソースからビルドする場合は、Self Handbook のビルド手順にあるとおり、Git・CMake・GCC(または Clang)・X・Ncurses が必要です。Self は 32 ビットプログラムのため、関連ライブラリもすべて 32 ビット版を揃える必要がある点に注意してください。
まとめ
Self は「クラスを持たないオブジェクト指向」という一風変わった立ち位置の言語ですが、その本質は「設計図ではなく実物を複製する」というシンプルな発想にあります。この「プロトタイプベース」という考え方は JavaScript に受け継がれ、実行時に最適化する技術は HotSpot VM をはじめとする後発のランタイムに影響を与えたとされています。言語そのものより、そこで培われた技術のほうが長く生き残った、というのはソフトウェアの世界らしい面白さです。興味を持った方は、ぜひ公式バイナリや GitHub のソースを手元で動かしてみてください。