第09回
■
■SqueakではじめるSmalltalk入門 第9回
■
本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。今回は、クラスを用いたSmalltalkプログラミングには欠かすことができないシステムブラウザの解説に先立ち、Smalltalkシステムにおいて「すべてがオブジェクトである」ことの意味をちょっと考えてみたいと思います。
システムブラウザ(System Browser)は、Smalltalkシステムにおける標準的なアプリケーションのひとつで、オブジェクトの定義の閲覧や編集をサポートするためのソフトです。ここでいう「オブジェクトの定義」は端的には「クラス」のことを示します。オブジェクトはどのクラスに属するかによって、どんなメッセージを受けることができるのか、いくつの状態(インスタンス変数)を内部に持つことができるのか…が決まります。
Smalltalkシステムでは、オブジェクトは必ず何かしらのクラスに属します。それをはっきりと意識させるためにオブジェクトのことを「インスタンス」という言葉を使って言い表すこともあります。インスタンスは英語で「実例」を意味する単語です。同じクラスに属するインスタンスは、原則として同じメッセージに対してまったく同じ振る舞いをします。また、よく知られるようにSmalltalkシステムは、データとプログラムを区別するようなことはせずに、オブジェクトのみでコンピュータシステムを成り立たせています。そこではクラスもオブジェクトであり、その振る舞いを定める何かしらのクラスのインスタンス、として扱われます。このクラスのクラスのことを「メタクラス」と呼び、「クラス名 class」というように表記します。
クラスStringのクラス => String class
クラスArrayのクラス => Array class
クラスDictoinaryのクラス => Dictionary class
クラスIntegerのクラス => Integer class
クラスFloatのクラス => Float class
...
ところで「class」はオブジェクトに送信することにより、そのオブジェクトが属するクラスをその返値として得ることができるメッセージでもあります。たとえば、「'squeak' class」を評価すると、'squeak'が属するクラス「String」(文字列)を得ることが可能です。では、この式の返値にさらにメッセージ「class」を送ると何が返ってくるでしょうか? 「'squeak'class」の返値である「String」に「class」を送信することになるので、クラスのクラスであるメタクラス「String class」が返ってきます。
('squeak' class) class " => String class "
ここで括弧は、最初に評価される式「'squeak' class」の返値へのメッセージ送信を明示的にするためのものなので本来は不要です。
'squeak' class class " => String class "
また、これは、
String class
としても、同じことです。すでにお気づきのように、先にご紹介した「クラス名 class」というメタクラスの表記そのものですね。「クラス名 class」という表記は、特定のクラスのクラスを表わすだけでなく、対応するクラスの名前を介して、それを得るためのメッセージ式にもなっている、というわけです。
余談ですが、クラスとメタクラスの関係は、通常のインスタンスとそのクラスの関係(一対多)と違って例外なく一対一で、クラスは対応するメタクラスの唯一のインスタンス(シングルトン)になっています。
(String) allInstances size " => 40845 "
"Stringのインスタンスは数あれど…"
(String class) allInstances size " => 1 "
"String classのインスタンスはただひとつ! もちろんそれは…"
(String class) someInstance " => String "
"クラス「String」です。"
さて。Smalltalkシステムではメタクラスもまたオブジェクト、つまり何かしらのクラスのインスタンスでなければならないはずです。これが何かも調べておきましょう。
(String class) class " => Metaclass "
メタクラスのクラスは「Metaclass」という名前のクラスでした。実は、すべてのメタクラスはMetaclassのインスタンスになっています。
(Dictionary class) class " => Metaclass "
(Integer class) class " => Metaclass "
(Float class) class " => Metaclass "
...
メタメタクラスと呼ぶべき「Metaclass」ですが、当然これもオブジェクトで、“ある”クラスに属しています。そう。それは、クラスとメタクラスのときと同様に、「Metaclass class」です。ただ、こうしてクラス、メタクラス、メタメタクラス、メタメタメタクラス…と続くと「いつまで続くのか…」と不安になられたかたもおられるかもしれませんね。でも、その心配には及びません。すでに申し上げたように、Metaclassは「すべてのメタクラスのクラス」なので、「Metaclass class」のクラスでもあります。
((String class) class) class " => Metaclass class "
(Metaclass class) class " => Metaclass "
MetaclassはMetaclass classのインスタンスであり、同時にまたクラスでもある…というのはちょっと不思議でズルをしているような感じもしますが、このカラクリにより少なくともメタメタメタ…と無限にメタなクラスが必要になる事態には陥らずに済んでいるので良しとしましょう。
このような仕組みは、いたずらにコトを複雑にするだけで無意味なものに見えるかもしれません。しかし、こうした“工夫”により、「Smalltalkシステムを構成するものは、すべてオブジェクトである」、「オブジェクトは必ず何らかのクラスに属する」という二つの単純な原則が貫かれていることが大切なのです。この原則のおかげで我々は、システム内で興味を持った“対象”が何であれ、それは例外なくオブジェクトであり、その素性や振る舞いを知りたければ(変えたければ)、属するクラスに当たればよい…、というスタイルに徹することが可能になります。そして、この「クラスを介して、オブジェクトを知り、変え、必要なら新たに設計する」作業を強力にサポートするアプリケーションのひとつが「システムブラウザ」というわけです。
次回は、システムブラウザの起動と指定したクラスのブラウズについてです。
このページを編集 (5267 bytes)
|
以下の 1 ページから参照されています。 |
This page has been visited 1163 times.