(スモールトーク)は、 のオブジェクト(およびクラス)、の徹底した動的性、 のタートル操作や描画機能に、アラン・ケイの「メッセージング」というアイデアを組み合わせて作られたクラスベースの純粋オブジェクト指向プログラミング言語、および、それによって記述構築された統合化プログラミング環境の呼称。ゼロックスのパロアルト研究所()で1970年代に約10年かけ3世代(-72、76、)を経て整備された。当初は、ダイナブックである のオペレーティングシステム的位置付けだったが、 のゼロックス社製品としての販売の可能性が同社上層部決定により完全に排除されたこと、発案者であるアラン・ケイの研究開発グループ離脱などを受けてダイナブック色は失せ、 のハードウェア技術を基にした商用マシン上で動作するプロの開発者向け統合化プログラミング環境「80」として1983年に発売されることになる。現在はシンコムより という製品名で主要なオペレーティングシステム向けに販売されている。豊富で整備されたクラスライブラリーは、特にオブジェクト指向プログラミングの手本とされ、デザインパターンの宝庫と称されるまで洗練されたものになっている。また、後世の多くのオブジェクト指向プログラミング言語に直接間接的に多大な影響を与えた。アラン・ケイが「オブジェクト指向」という言葉を創った当初は、 システムが体現した「パーソナルコンピューティングに関わる全てを『オブジェクト』とそれらの間で交わされる『メッセージ送信』によって表現すること」を意味していた。しかしのちに、 の設計者として知られるビャーネ・ストロヴストルップが(自身、 の影響は受けていないと主張する) の設計を通じて整理し発表した「『継承』機構と『多態性』を付加した『抽象データ型』のスーパーセット」という考え方として広く認知されるようになった(カプセル化、継承、多態性)。現在は、両者の渾然一体化した曖昧な概念として語られることが多い。 は、オブジェクトへのメッセージ送信を率直に記述する表記の特殊性や、制御構造をもたずオブジェクトへのメッセージ送信の形で記述する徹底ぶりとも併せて、C言語や などの構造化プログラミングの流れを強く受け継ぐ言語、およびその開発手法に慣れた開発者にとって極めてとっつきにくい言語・環境であるといわれている。このことは、 が単なるプログラミング言語ではなく、従来のオペレーティングシステムの概念をも包括する「環境」であることが一つの理由である。 を単なる言語としてとらえると、他の言語と比較したとき、使用するオペレーティングシステムのグラフィカルユーザインターフェースに全く従わないなど、その独自性が大きな「欠点」として映る場合もある。これは や など、旧来の 環境、つまりダイナブックコンピュータ環境の要素を引き継ぐ統合開発環境を通じて 言語や処理系を学ぶなら、多かれ少なかれ新たなオペレーティングシステムに接するような心構えを持つべきことを意味する。 環境から見た 言語は、いわば などのシェルに近い。 環境内であればどこでもマウスで選択した文字列を のソースコードとして実行できるためシェルにコマンドを打ち込んだ時の様に簡単な問い合わせをすぐ実行できるようになっている。例えばオブジェクト(クラスやメソッドも含む)の構造を調べたければ、そのオブジェクトにセレクターあるいはセレクターを使ったメッセージ式を書き、そのメッセージ式をマウスで選択してdo it(WindowsであればCtrl+Dを押す)すれば良い。また、設定値の指定に 言語のメッセージ式が使われる。現在設定されている値がメッセージ式として取得でき、値の設定をメッセージ式として指定する。この設定値を指定するメッセージ式は 環境の実行中に設定用のウィンドウから入力される。 環境は、 環境の実行方法として現実のハードウェアに依存している機械語命令を使わず、現実のハードウェアから独立した中間言語命令(仮想機械に対する機械語命令)を仮想機械により実行する仮想機械方式を採用している。 の中間言語命令は、全てイメージファイルというファイルに書き込まれ の仮想機械はそのイメージファイルを読み込んで 環境を実行する。この仮想機械方式による の実行方法は の言語仕様にも含まれている。なお、 が導入したこの仮想機械方式はのpコードマシンからアラン・ケイが着想を得たものである。イメージファイルは、 環境の実行状態をそのまま保存したファイルである。イメージファイルは 環境実行中に生成された全てのオブジェクトを直列化して保存することで 環境の実行状態を保存している。この直列化されたオブジェクトには、 の中間言語も含まれている。イメージファイルに含まれる中間言語命令は、 自身によって記述されたコンパイラーによってソースコードから翻訳された、バイト列のオブジェクトである。中間言語を実行している仮想機械も一般的には で記述される。ただし、仮想機械で動く の実行イメージが実行環境の機械語で直接動作する仮想機械にはなれないため、 で書かれたソースコードを一度Cのソースコードに変換し、C言語のソースコードから実行環境で直接動作する仮想機械を生成するという形式をとっている。 の実行環境が全く存在しない初期の状況ではコンパイラーも仮想機械も で用意する事はできない。このため の初期段階ではC言語によりコンパイラーや仮想機械が実装されていた。GUIを使わないような特殊なものを除き、大半のSmalltalk環境では次のようなGUIツールが用意されている。Smalltalkの開発ではこれらのツールを使って開発する事が半ば前提となっている。Smalltalk環境内に存在する全てのクラスを(存在する場合は名前空間も)表示/編集できるツールで、Smalltalk開発において中核となるツールである。言うなれば出力しかできないコンソールといったツールで、プログラムの実行結果を簡易的に表示したいときに使われるツールである。Smalltalk環境内でTranscript変数に書き込まれたメッセージは、全てこのTranscriptに表示される。言うなればコンソールの入力側とテキストエディターを組み合わせた様なツールである。一見すれば書いたコードを実行できるだけの簡易的なテキストエディターにしか見えないが、WorkspaceはWorkspace変数というWorkspace固有の変数を持っており、Workspace内で実行されたSmalltalkコードの実行結果を保持することができる。このため、長いコードを書くような用途では使わず、Smalltalk環境に対するパッケージの追加や、環境設定、ファイルの一時的な操作など一時的な操作を実行する場所として使われる。オブジェクトの内部構造を再帰的に表示するツールである。また、多くの場合オブジェクトの編集が可能でありWorkspaceと組み合わせてオブジェクトを組み立てていくことが可能である。例えば画面部品をWindowを表すオブジェクトに組み込み、クラス変数に格納するといった具合である。Inspectorに限らずSmalltalk環境全体に共通することであるが、オブジェクト内の変数を表示するときは内部構造そのままではなくオブジェクトの文字列表現で表示する。このため内部がHash map等複雑な構造になっている場合でもcodice_1といった読み易い表示となる。言語として が目指したもの。それは計算機を計算機の集合体として構築し、さらに計算機を構成する個々の計算機も計算機の集合体で構築するというように、再帰的な計算機を構築することであった。この再帰的な計算機を構築している無数の計算機は、個々の内部には干渉せずメッセージによる通信のみによって相互作用を発生させ目的の計算を完遂させる。ここでいう計算機が ではオブジェクトという形で実装された。この設計思想の誕生は、とB5000の設計者らが会談した際の次の発言をアラン・ケイが聞き「計算機の全体を計算機とみなした場合、その計算機の構成要素を計算機に分解するのではなく関数やデータ構造に分解したいと誰が思うのか」と疑問を浮かべた事がきっかけとなっている。ここで言及された再帰という概念は、オブジェクトの成立以外にも の至るところに影響を与えている。 の言語仕様は原則として非常に単純なため、環境もしくは処理系の相違による互換の有無は、クラスライブラリーの差異程度に由来するもの(ある意味、バージョンの違いもこれも含まれる)から、言語仕様自体の改変に由来のものまで空間的に連続で多岐にわたる。このため、単に として語弊のある場合、一般にその環境および処理系の呼称もしくは商標(必要ならそのバージョン)をして他と区別するために用いる慣習がある。「codice_12」のようにダブルクオーテーションでくくった文字列がコメントとして扱われる。主な定数表現には次のようなものがある。定数ではないが、よく用いられるオブジェクトの生成式には次のようなものがある。言語機能の様に見えるが「codice_13」や「codice_14」などはただのセレクターであり、 の使用者も同様の機能を作ることが出来る。一時変数は宣言が必要で、「codice_15」で挿むように記述する。変数への代入は「codice_16」。古い処理系では「codice_17」が使用された(字形は「←」)。変数に型はなく全てハンドルになっている。他の言語で予約語にあたる擬変数は codice_18、codice_19、codice_9、codice_21、codice_22、codice_23 の6つ。codice_18 と codice_19 はそのメソッドを呼び出したメッセージの受け手(レシーバー)を、codice_9 と codice_21 と codice_22 はそれぞれ codice_8、codice_30、codice_31 に属するソルインスタンス(唯一の実体)を、codice_23 は実行中のコンテキスト(スタックフレーム)を参照するのに使える。codice_18 と codice_19 は同種のオブジェクトだが、メッセージ式でメッセージレシーバーに指定されたときのメソッド検索の起点が異なり、codice_18 ではオブジェクトが属するクラス、codice_19 ではその基底クラスである。 では「メッセージ式」と呼ばれる書式でコードを記述する。メッセージ式は「レシーバー」に「メッセージ」を送ることを表すためのもので、そのままと記述する。メッセージはさらに、呼び出されるされるメソッド(処理手順)の名前を表す「メッセージセレクター」と0個以上の引数の組み合わせからなる。ただし の場合必ずしもセレクターとメソッド名は一致しない。また、メッセージの送り先はメソッドではなくブロックや外部の関数になっている場合もある。セレクターは引数の数だけコロンを自身に含まなければならず、メッセージとして記述する際にはコロンの直後に引数を挿入する。引数なしのメッセージを単項メッセージ、そのセレクターを単項セレクターと呼び、引数ありのメッセージをキーワードメッセージ、そのセレクターをキーワードセレクターと呼ぶ。メッセージ記述の際に引数の挿入により分断されたキーワードセレクター断片(例えば codice_37 なら codice_38 と codice_39)をキーワードと呼ぶが、あくまで便宜的な呼び名に過ぎず、そうした言語要素は存在しない。他の言語に見られる「キーワード引数」のようなに省略できるものではなく、また引数順を入れ替えられるものでもない。セレクターは原則としてアルファベットと数字と0個以上(かつ、引数と同数)のコロンから成るが、例外として二項演算を模した記述が可能となるように記号のみから成る引数1つのセレクターを使ってメッセージ式を記述することもできる。これを二項メッセージ、そのセレクターを二項セレクターと呼ぶ。この場合、上の「codice_40」では、「codice_41」がレシーバーで「codice_42」がメッセージである。通常の処理系では、単項メッセージ、二項メッセージ、キーワードメッセージの順で評価される。二項メッセージ間で乗除の優先はない。セミコロン「codice_43」でメッセージ式を区切る事により、1個のレシーバーに対して複数のメッセージを送ることが出来る。これをカスケード式という。カスケード式を用いて書いた上記の文は、カスケード式を用いない次の文と等価である。複数の式を順次実行する場合は、式をピリオドで区切る。メソッドを中断し戻り値を指定するには復帰文「codice_44」を使う。言語機能として持つ制御構文は復帰文を除いて存在せず、復帰文以外の制御は制御構文と同等の機能を持ったメッセージ式で代用する。ブロックは、他の言語で言えば無名高階関数やクロージャーに該当する機能である。ただし のブロックは関数ではなくオブジェクトである事に加え、無名高階関数というより制御構文としての性格が強くなっている。並列実行の基本単位にもなる。ブロックは、引き数の数毎に複数定義された「codice_45」を含むメッセージを送る事で、ブロック内に記述されたメッセージ式を実行し結果を返す。ブロック内のcodice_46は引き数であり、「codice_15」以降は「codice_45」を含むメッセージが送られた際実行するメッセージ式である。「codice_45」を複数ならべたセレクターは4個程度まで( codice_50 )しか定義されておらず。5個以上引き数を取る場合は、配列を引き数とするcodice_51を使う必要がある。メソッドが値を返す際は、復帰文の記述が必要となるがブロックの場合は値を返すのに復帰文は必要ない。最後に実行されたメッセージ送信の結果あるいは、最後に書かれた値が戻り値となる。ブロックは制御の基本となるオブジェクトであるため、「codice_45」を含むメソッド以外にも膨大なメソッドを持っている。ただし、後述する他の制御構文はブロックに対しcodice_53セレクターまたは、codice_54セレクターを使ったメッセージしか送らない。ブロックにはcodice_45と合わせてよく使われるセレクターとして「codice_56」がある。codice_56の振る舞いは、ほぼcodice_45と同じであるが、ブロックがメッセージに含まれる引き数を無視できるという違いがある。codice_56はブロックによる分岐制御が主目的であるが、分岐の基準になったオブジェクトを参照する場合もあるようなセレクターで使われる。典型的な例は、オブジェクトがnilで無いときだけブロックを実行するcodice_60である。条件分岐は codice_61 セレクターを用いたメッセージ式として、条件式の結果の真偽値へのメッセージ送信の形で次のように記述する。条件分岐の制御において、他の言語でいうcodice_64に直接該当する文は存在しない。多態性を利用して分岐するか、次のように連想配列を利用して分岐するため不要である。但し一部の処理系では、次のようなcodice_64に類似した書き方ができるものも存在する。反復制御においてcodice_66 に直接該当する文は存在しない。代わりに回数を指定した反復がある。回数を指定した反復は、整数型へのメッセージ送信の形で次の様に記述する。現在の反復回数を参照しながら反復する事も出来る。codice_66 に該当する文は存在しないものの、codice_68 に該当する文は存在する。codice_68 に該当する反復は、ブロックに対するメッセージ送信の形で次の様に記述する。codice_70 セレクターは、条件が真である間反復する事を意味している。逆に条件が偽である間反復する codice_71 というセレクターも存在する。また codice_72-codice_68 に該当する文も存在する。codice_72-codice_68 に該当する反復は、ブロックに対するメッセージ送信の形で次の様に記述する。C言語の codice_77 や の codice_78 に相当する反復脱出は codice_23 に対し codice_80 セレクターを使ったメッセージを送る。codice_23 には、引き数を取り、引き数を脱出するブロックの戻り値として返す codice_82 セレクターや、戻り先のメソッドを指定する codice_83 セレクターなど多数の codice_84 系セレクターに対応するメソッドが定義されており、他の言語には珍しい多様な反復の脱出方法を備えている。 にも例外処理機構が存在する。こちらも、その他の構文と同じくメッセージ式とブロックによって実現されている。例外処理は次の様に記述する。例外の制御はメッセージ送信毎に連結リストとして積み上げられたコンテキスト情報の末端のコンテキスト(メソッドスタック)を表す codice_23 オブジェクトを操作し、コンテキストを巻き戻す事で実現されている。複数の例外は、codice_86・・とcodice_87を繰り返し記述して補足する事もできるが、次の様に例外の型をcodice_88で並べて補足する事も出来る。なお、では正常な結果を返せないエラー(間違い)と通知両方を合わせたものが例外である。例外は正常な戻り値を返せない場合と割り込みの様に非同期な通知に利用される。では、標準で並列処理が存在する。並列処理は次の様に記述する。並列処理はスレッドに類似するプロセスという仕組みにより実装されている。プロセスは環境内で構築された並列処理の仕組みであり、グリーンスレッドで実装されている事が多い。このため、プロセスは論理的に非プリエンプティブなスレッド(グリーンスレッド)を前提しており、現在実行している処理を切り替える切り替え点を必要とする。論理的な前提は非プリエンプティブではあるものの、POSIX環境で動作させたGNU Smalltalkの様に実際はプリエンプティブなスレッドで実装されている場合もある。プロセスは他のプロセスから割り込みとして任意の例外を投げる機能があり(記述方法は環境によって異なる)、切り替え点はプリエンプティブなスレッドを使う場合でも例外の発生地点として機能する。 は、クラスの定義をメッセージ式による実行環境へのクラスオブジェクトの登録として実現する。他の言語と異なりクラスオブジェクトの登録は単なる定義ではなく実行環境に対する操作である。1度クラスオブジェクトを登録してイメージファイルを保存すると、明示的にクラスオブジェクトを削除しないかぎりはクラスオブジェクトがイメージファイルに残り続ける。 環境に対するクラスオブジェクトの登録は次の様に記述する。codice_89 と codice_90 を除いては、 から派生した言語のクラス定義と概ね同じである。特筆すべきはクラス変数とプール変数の扱いである。 や の利用者が codice_91 の名前を初めて見た際、静的変数(クラス変数)を連想しがちである。しかし、 や においての静的変数(クラス変数)に該当する変数の指定はプール変数でありクラス変数ではない。 のクラス変数は、クラス変数の所属するクラスオブジェクトとインスタンスオブジェクトのみで使用される変数であり、クラス変数が所属するクラスオブジェクトから派生したクラスオブジェクトやそのインスタンスオブジェクトでは共有されない。これは、 ではクラスがオブジェクトである事と共に、派生クラスのクラスオブジェクトは、基底クラスのクラスオブジェクトから生成された別のオブジェクトである事を意味している。派生したクラスのインスタンスオブジェクトでも変数を共有したい場合はプール辞書を使用する。しかし、クラスの登録はあくまでメッセージであり自由に作れるため、実行環境には大抵その他のメソッドが用意されている。例えば、近代的な 環境の一つ では、次のセレクターに対応したメソッドが用意されている。クラスオブジェクトには、クラス変数とは別途、クラスオブジェクトが codice_92 クラスから派生したインスタンスとして状態を持つためのインスタンス変数がある。このクラスオブジェクトのインスタンス変数はクラスオブジェクト内だけで共有され、インスタンスオブジェクトからは直接使用できない。メソッド(処理方法)の登録は、コード文字列を引数として与えたクラスへのメッセージ送信でも行えるが、通常は環境に組み込まれたクラスブラウザ(システムブラウザ)と呼ばれるGUIツールを用いる。メソッドは、「メッセージパターン」と呼ばれるメッセージ式のメッセージ部分を模した書式に続けて0個以上のメッセージ式を連ねることで記述する。例えば、前出の、レシーバーか引数を比べてより小さな方を返す「codice_93」というメソッドの登録は次のようなものになる。一行目の「codice_94」がメッセージパターンで、メソッド名(セレクター)と仮引数となる擬変数の宣言を兼ねる。念のためここでメソッド名は「min:」、仮引数となる擬変数名は「codice_95」である。メッセージパターンのあとに処理を続けて書くこともできるが、通常は行を改めて(さらに、ここでは省いたが慣習としてメソッドの説明をするコメントを書き、それに続けて)処理を記述する。なお、メッセージパターンのみで具体的な処理を記述せずにメソッドを登録した場合を含め、復帰文による明示的な戻り値の指定が無い場合、メソッドは戻り値として常に codice_18 を返す。したがって では値を返さないメソッドを書くことはできない。は、多くの動的型付け言語やの様にクラスがオブジェクトである。このためではインスタンスオブジェクトと同様にクラスオブジェクトを変数に束縛してメッセージを送ることができる。クラスオブジェクトは、オブジェクトにcodice_97メッセージを送ることでも取得できる。 のブロックは一種の制御構文であるという性質上、復帰文が他の言語と比べ極めて異質な振る舞いをする。上記のメソッドを登録したオブジェクトにcodice_98 セレクターを使ったメッセージを送ると結果としては何が返ってくるか。 以外の言語では codice_99 が返ってくるのが一般的であるが では codice_100 が返ってくる。 はブロック内の復帰文からでもメソッド自体を抜けることができるようになっている。この例では、「codice_101」を評価し、codice_102 中の「codice_103」で制御が戻ると codice_104 自体も中断して結果を返す。そして codice_104 は戻り値として codice_102 が戻した codice_100 を戻すようになっている。上記の様なメソッドをまたいでブロックを評価する場合はどうなるだろうか、この場合も は codice_104 の戻り値として codice_102 の戻り値である1を返す。 はブロック内で復帰文が実行された際、ブロックの生成地点の呼び出し元までコンテキストを巻き戻すようになっている。この特性により では、codice_61 セレクターを使った分岐でメソッドを中断したり codice_111 セレクター等を使った反復処理を復帰文だけで中断する事ができるようになっている。ただし、上記の様にブロックを生成したコンテキストと、ブロックを評価する際のコンテキストが枝分かれする様な場合は復帰文を実行する事はできない。この場合は codice_112 が例外を出力し処理が停止してしまう。メソッドに対する注釈(Pragma)は、メッセージ式だけではどうしても実現が難しい機械語でしか記述できない演算子の実装や主記憶領域の確保、仮想機械外部との入出力等の実現や、特定の目的のメソッドを自動で列挙するといった目的で使用される特殊構文である。いくつかの注釈はSmalltalk環境に組み込まれているが、利用者やライブラリーの提供者が注釈を定義する事も出来る。メソッドに対する注釈はメソッドの翻訳時に評価されるため、メソッドにしか記述でない。Behaviorのcodice_113による評価などメッセージ式をメソッドの外部で評価する場合は、評価対象の式に注釈を含める事はできない。具体的にはSmalltalk環境のWorkspaceに注釈を記述して評価するとエラーとなる。メソッドに対する注釈は次の様に記述する。codice_114とcodice_115で囲まれた範囲は、メッセージ式のメッセージ部分と同じになる。但し引き数を取らない注釈の記述はできない。次にメソッドに対する注釈の具体例を挙げる。注釈はSmalltalk環境によって異なり、どの環境でも次の注釈が使えるわけでない事に注意すること。Smaltallkでは、Smalltalk環境全体で参照できる大域変数を作成する事が出来る。大域変数は同じく大域変数であるSmalltalk変数に格納されたcodice_116のインスタンスオブジェクトにメッセージを送って作成する。また、大域変数の削除もcodice_116のインスタンスオブジェクトに対するメッセージ送信となっている。codice_116は一種の連想配列であり、Smalltalkの大域変数は、Smalltalk変数を介す事で連想配列として操作する事が出来るようになっている。なお、Smalltalkのクラス名と大域変数は同じものであり、クラス名にオブジェクトを代入すれば、そのクラスを破壊してしまうことが出来る。また、Smalltalkオブジェクトが格納されたSmalltlak変数もオブジェクトを代入し破壊する事が出来る。このように大域変数を代入により破壊してしまった場合は、最悪Smalltalk環境が起動しなくなる事態に陥り非常に危険である。このためSmalltalkではよほどの理由がなければ大域変数を使うべきではない。プール辞書は、クラスの変数として連想配列または、他のクラスオブジェクトのクラス変数を取り込むという機能である。取り込む連想配列の要素やクラスオブジェクトのクラス変数はプール変数と呼ばれる。連想配列やクラスオブジェクトは大域変数でなくてはならない。プール辞書には複数の連想配列やクラスオブジェクトを指定できるが、プール変数が重複した場合は、先に指定した連想配列やクラスオブジェクトのプール変数が使われる。Pharo, GNU Smalltalkといった近代の環境では、定数以外に式の結果を指定可能な非定数要素の配列定数を使用できる。配列の要素は空白ではなくcodice_119で区切る。継続渡し形式を支援する機能として継続があり、PharoやGNU Smalltalkで使用できる。もっぱら反復の中断や、メソッド内の処理を飛ばすために使われる。継続の使用は次の様に記述する。遅延評価を支援する機能として生成器があり、PharoやGNU Smalltalkで使用できる。生成器はCoroutineにも利用できる。生成器の使用は次の様に記述する。生成器を使って処理を作ることは多くないが、配列などを使用する際、間接的に使用していることが多い。 のプログラムは基本的に中間言語としてイメージファイルの中に格納され、ソースコードの編集は のGUI環境から行われる。このため基本的にファイルという形で のソースコードやプログラムを目にすることはない。しかし、ソースコードの交換目的などでどうしても 環境外でソースコードを管理する必要がある場合に備えファイル用の構文が存在する。ファイル用の構文は次のようになる。本来他の言語の様なブロックが存在しないため、ブロックとして「codice_120」が使用される。クラスの登録は「codice_120」の一組で囲まれる。メソッドはプロトコル毎に「codice_122」というブロックで囲まれる。一つのプロトコルには複数のメソッドを定義でき、メソッド同士は一個の「codice_120」によって区切られる。ちなみに、クラス登録は単なるメッセージ送信であり特別な文ではないため、クラス登録に使用しているブロックも次のように単純なメッセージ送信の記述に使用する事が出来る。ファイル用構文で記述されたメソッドの登録は、可読性や記述性の面からメッセージ式からかけ離れた変則的な構文が使用される。しかし、この変則的な構文を用いなければメソッドを登録できないわけではなく、次のように通常のメッセージ式でメソッドを登録する事も出来る。上記では、クラスオブジェクトcodice_124のプロトコルcodice_125に対し、メソッドcodice_126を登録している。 において、継承とは特殊な委譲に過ぎない。このため、例えば上記のクラスオブジェクトの生成では、codice_127 クラスオブジェクトの基底クラスオブジェクトとして codice_6 を指定しているが、処理系によっては下記の様に codice_129 メッセージを送る事で、基底クラスに別のクラスオブジェクトを指定する事が出来る。処理系により不可能な事もあるがクラスオブジェクトだけでなく、インスタンスオブジェクトから派生することも出来る。なお通常、派生元の基本となるProtoObjectやObjectはnilから派生しており継承関係は再帰的に循環している。 において、メッセージ、セレクター、メソッドはそれぞれ別物である。 系統の言語の様にオブジェクトに対しメッセージを送るという事は単なる比喩ではない。あるオブジェクトに対し codice_130 というセレクターを使ったメッセージを送る事を考える。この時、 においては codice_131 というメソッドが必ず呼ばれる保証はない。例えば「hello」メッセージを受け取るオブジェクトが codice_131 メソッドを実装していなければレシーバーに指定されたオブジェクトの codice_133 メソッドが呼ばれる事になる。なお、多くの の処理系では codice_133 の引き数で得られたメッセージを返すだけのクラスが用意されている。例えば 環境のひとつである ではメッセージ作成用クラス codice_135 が用意されており次のようにメッセージを拾い、他のオブジェクトに渡すことが出来る。また、セレクターとメソッドが独立していることを利用して一つのメソッドを複数のセレクターに結びつける事もできる。メッセージにはセレクターと引き数が含まれている。このため受け取ったセレクターと引き数を編集する事も出来る。プログラミング言語一般の概念として型検査をソースコードの翻訳時に実行するか、実行時に実行するかにより静的型付けと動的型付けという区分が存在するが、は、そのどちらでもなく型なし言語()に区分される。 の場合、変数に対する操作は全てメッセージ送信であり、変数の種類(型)毎にできる操作は決まっていない。また、オブジェクトに対しメッセージを送った場合、そのオブジェクトがメッセージに対応するメソッドを持っていなくとも実行環境がエラーを発生させる事はない。メッセージに対応するメソッドが存在しない場合、例外を出すか無視するかは、クラスに実装されたメソッドの内容次第である。したがって には型付けの概念はない。例えば、 の codice_135 は全てのメッセージを拾うため、どんなメッセージを与えられても例外が発生することはない。また、GNU Smalltalkではnilから派生したクラスのオブジェクトに存在しないメソッドに対するメッセージを送ると何も反応しない。ちなみに は基本的に中間言語に翻訳され、翻訳時にエラーを発生させるため構文検査は静的である。制御構文の節で述べた通り、の殆どの制御構文はメッセージ式である。に明るくないプログラマーからは言い方や見方を変えただけと捉えられがちである。の制御構文は実際にメッセージであるがゆえに究極には制御分の構文要素を次のように変数に分解してしまうことが出来る。変数に分解した分岐制御の例:これらの変数に分解された構文要素は、どのクラスのオブジェクトで無いといけないという制限はない。送られたメッセージを処理することさえ出来ればあらゆるオブジェクトに置き換える事が出来る。Smalltalkでは高速化のためいくつかのメッセージを特別扱いする。これを特殊セレクター()という。典型的な例はcodice_61である。下記のコードはでは「ifTrue: [5] ifFalse: [6]」を評価した時にメッセージが送られる訳ではなく、バイトコードレベルでインライン展開され飛越し命令の表現に置き換えられる。このため実際にcodice_138 という名のメソッドが呼ばれることもない。また、trueやfalse以外に上記のようなBoolean用のメッセージを送ると処理系によってはMustBeBoolean例外を発生させる。このように頻繁に使用する分岐や反復を特別扱いすることで性能低下を防いでいる。セレクターと名がつくが特殊セレクターは、特別扱いする条件が引数の状態を含んでおり、たとえ同じセレクターを使ったメッセージでも引数が条件に一致しなければ特別扱いしない。例えば下記のように引数に直接ブロックを指定していない場合では多くの処理系(VisualWorks, GNU Smalltalk等)は特別扱いせずメッセージ送信を実行する。特殊セレクターはあくまで高速化の手段であるため種類は処理系によって異る。どの処理系が何を特殊セレクターとして扱うかは処理系ごとに提供される説明資料に記述されている。クラスオブジェクトもオブジェクトであるため、所属するクラスが存在している。クラスオブジェクトが所属するクラスはcodice_2というクラスのインスタンスオブジェクトである。codice_2も当然ながらクラスに所属しており、再帰的にcodice_2に属するようになっている。クラスオブジェクトが所属するcodice_2のインスタンスオブジェクトは特殊なオブジェクトであり、クラスの継承階層と同様に継承階層を持っている。クラスオブジェクトはMetaclassから生成された単なるオブジェクトで有ることから、Smalltalkが標準で提供するクラスオブジェクトとは異なる構造の独自をもつクラスオブジェクトを作ることができる。例えば以下のようにメソッドの変わりにブロックを持つ無名クラスを作成することも出来る。文法の節で述べた通りでは定数も全てオブジェクトである。どんな定数であれcodice_143やcodice_144といった基本的なセレクターを使ったメッセージを受け取ることが出来るため、基本的な操作であれば定数と他のオブジェクトを区別する必要はない。 は、任意の広さで確保した領域を持つ可変長オブジェクトを作ることが出来る。には配列を表わすためArray等が存在するが、これらのクラスオブジェクトは可変長オブジェクトを使って構築されている。可変長オブジェクトの領域は、オブジェクトの生成したときの一度だけしか広さを指定できない。また、クラスオブジェクトの登録時にcodice_145で始まるセレクターを使っている必要がある。変数を表す識別子については、1文字目に大文字と小文字のどちらを使うか、大域変数か否かを基準にして決めることが慣習になっている。環境自体も大文字小文字の使い分けを認識しておりメソッドを翻訳する際小文字の変数は局所変数かメンバーとして定義していないと、警告が発生したり翻訳失敗になる。クラス名が大文字から始まるのは、クラス名が大域変数だからである。よく使われるクラス以外の大域変数:セレクターを表す識別子については、基本的に1文字目に小文字を使うが、メソッドが存在するセレクターを避けたい場合は大文字を使う事が慣習になっている。GNU SmalltakやVisualWorksで用意されている名前空間は、大文字のセレクターを使う典型的な例である。なお、名前空間が使える環境の多くは、翻訳時に名前空間の名前解決できる「.」区切りの拡張構文が用意されており、実際にはこちらの構文が使われることが多いため、セレクターを使った名前空間の指定を見る機会は少ない。オブジェクトの生成には codice_146 セレクターを使ったメッセージを使う。他の言語と違い、codice_147 は演算子ではない。ただし、実際の初期化に codice_147 メソッドが使われる事は多くない。実際には慣習としてクラスの作者が新たに登録したインスタンス・クリエイションと呼ばれる codice_147 とは別の初期化用メソッドが使用される。インスタンス・クリエイションは一般的なクラスオブジェクトのメソッドであり、そのメソッドの内部で 「codice_147」メッセージやその他のインスタンス・クリエイションを使って初期化済みのオブジェクトを生成する役割を持っているだけで基本的にその他のメソッドと変わらない。一般的にcodice_158というプロトコルに登録される。具体的には次のように使われる。また、 はクラスメソッドを上書きできるため、インスタンス・クリエイションを次の様に実装する事で基本的な初期化処理を派生元のクラスに任せることができる。上記は、2次元座標用のクラスオブジェクトのインスタンスオブジェクトを初期化する派生元のクラスオブジェクトに実装されたインスタンス・クリエイションである。このクラスオブジェクトを継承した2次元座標用のクラスオブジェクトではcodice_160セレクターを使ったメッセージに対応するメソッドを実装する必要はない。インスタンス・クリエイションを利用したパターンは では広く利用され、いたる所で見ることが出来る。 では、単一の値を出し入れするメッセージの事を特にアクセッサ―と呼ぶ。引き数の有無により値の入出の方向を区別する。例:定数は、単に定数を返すアクセッサ―で定義する。C言語の影響を受けた言語のように定数を#defineや変数で定義するという慣習はない。 では、非常に利用頻度の低いインスタンス変数やクラス変数を管理する方法として附帯情報()というパターンが使用される。附帯情報はインスタンス変数やクラス変数などの内部変数の代わりに連想配列によりオブジェクトを保持する仕組みである。附帯情報の意味合いとしては、附帯情報と言うより所有物あるいは付帯情報という意味の方が適切である。附帯情報の使用例:附帯情報が有効な身近な例としてはXMLやHTMLのタグ属性が挙げられる。例えばHTMLの codice_161 属性や codice_162 といったイベント属性は、必ずしも全てのタグで使用されることはない。特にイベント属性については一つのHTML上に一切記述されない事もよくある。この様な使用頻度の低い属性のためにオブジェクトに一個一個変数を定義するのは記憶領域の無駄である。ましてや codice_162、codice_164、codice_165等大量に属性があればこの無駄は馬鹿にならない。この様な無駄を省くために では附帯情報というパターンがよく使用される。全てのインスタンス変数やクラス変数は原理的に全て附帯情報によって表現することが出来る。この点に着目しオブジェクトに所属する変数を全て附帯情報に置き換えた言語が後の であり、 である。これらの言語でオブジェクトに所属する変数をプロパティーと表現するのは、この における附帯情報(プロパティー)に由来するもので、附帯情報の仕組みの有無に関わらずインスタンス変数やクラス変数をプロパティーと表現するのは間違いである。附帯情報は や においては当たり前の様に使用されている。しかし、 においては附帯情報を多用する事はデバックを著しく困難にするため不適切な作法とされており、HTMLの属性の様に本当に使用頻度の低い変数だけを附帯情報で扱い、常用する変数に附帯情報を乱用すべきではないと言われている。 以外の言語において、配列の範囲外にある配列要素の操作や、値の代入されていない連想配列の操作は、次の例のように操作の前に一旦判定を行なって例外処理するか、例外機構を利用する方法が一般的である。一方 では、配列の範囲外操作の様に単純で頻発するような処理では、次のように予めメッセージに例外処理をブロックとして渡してしまう方法が一般的である。予め例外処理をメッセージに含めることで、単純な例外処理をより簡潔なものとしている。この方法は、 独自の復帰文と組み合わせる事でより柔軟な制御をする事ができる。次の処理は、連想配列に値が見つかればそれを表示し、値が無ければ何もしないという処理であるが、処理の中断の判定と連想配列からの値の取り出しを一度のメッセージ送信だけで実現している。では、ブロック内だけ資源を確保しブロックの終了後に資源を開放するというブロックによる資源の開放が行われる。ブロックによる資源の開放では、資源の確保と同時に資源の開放を強制できるため開放忘れや例外による開放漏れを防ぐことができる。のcodice_166に類似するが、codice_166を書き忘れたままcodice_147できない分さらに強力である。 は反復処理のための基本構文を備えているが、ある値の生成器(入出力等)やある集合要素から要素を取得するときに基本的な反復構文を使う事は稀である。 では、値を列挙するために値の生成器や集合要素に送るべきメッセージが概ね決まっており、値を取り出す際は極力、列挙メッセージ()を使用する事が作法となっている。次に列挙メッセージの送信例を示す。配列に対する列挙メッセージの例:実行結果:数値に対する列挙メッセージの例:実行結果:列挙メッセージで使えるセレクターは codice_169 の様に全ての要素にブロックを適用するだけの単純なセレクターだけでなく、現在の集合要素の要素を操作した上で新しい集合要素を作成する codice_170 や、集合要素から条件に一致する要素だけを抜き出し、新しい集合要素を作り出す codice_171、集合要素の中から特定の要素を見つけ出す codice_172 など様々なセレクターがある。処理系によっては codice_173 などSQLに類似したセレクターに対応するメソッドを多数用意しているものもある。 では集合要素や値の生成器自体にこれらのメッセージを受け取れるよう実装する事で、集合要素のデータ構造や、生成器の入力元などの構造に依存せず最適な反復処理を実現できるようになっている。これらの列挙機能は近年の言語において codice_174 やcodice_175、LINQ等言語機能として賄われつつあるが においては、単にライブラリーの慣習として実現されている所が特徴的である。Smalltalkでは一般的にオブジェクトにcodice_176というセレクターを使ったメッセージが送られた場合、オブジェクトを別のクラスのオブジェクトに変換する。例えば次の様な変換がある。Stringの変換による具体例(変換結果は処理系依存):オブジェクトを別のオブジェクトに変換するメソッドやメンバー関数が用意されている事は、Smalltalkに限らず他の言語でも一般的であり珍しい事ではない。Smalltalkの慣習として特徴的なところは、既存のクラスにこのオブジェクトの変換をユーザーやライブラリーの作者が自由に組み込んでいる所である。例えばSmalltalkの処理系であるPharoでは、初期状態で基本的なクラスであるStringに54個ものcodice_177で始まるメソッドが定義されている。この大量の変換メソッドは、メソッド追加した際すぐに影響を判断できるためメソッド追加に対し寛容的なSmalltalk独特の空気を象徴している。しかし、既存のクラスにメソッドを追加すればライブラリーをマージした際、意図しない衝突を生むため多用は避けるべきであるとの意見も存在する。イベントハンドラーを定義する方法として、では次のようにセレクターと、レシーバーとなるオブジェクトを指定する方法が一般的である。同様にイベントハンドラーを指定する別の方法としては、ブロックを指定する方法が考えられる。しかし、イベントハンドラーにブロックを使う方法は、セレクターとオブジェクトを指定する方法のようにcodice_178だけでブロックを抱えたオブジェクトがどんな処理を実行するか判断できないうえ、ほとんどの環境はブロックの直列化に対応しておらず直列化もできなくなってしまうため、の文化においては避けるべきとされる。このセレクターとオブジェクトを指定したイベント処理の方法は、Objective-Cの文化にも引き継がれており等のライブラリーにて頻繁に目にすることができる。Model View Controller(MVC)は から生まれた、制御(コントローラー)と情報(モデル)、そして情報の表現方法(ビュー)の3つを分離しクラスオブジェクトの再利用性を高め、実行時に情報と表現の組み合わせを変更できるようにした設計方針である。 の世界でMVCは更に表現を担当するクラスに既定の制御を取り込む仕組みを持たせることで へと発展した。 はクラスライブラリーの基礎部分からMVCやMVCから派生した設計方式で使用されるモデルの構築を支援する仕組みを持っており、 以外の言語と比べモデルの構築が格段に楽になっている。次にモデルの動作を確認する最低限のコードを示す。モデルの登録:モデルの監視側登録動作の確認:モデルの支援機構は全て codice_6 クラスオブジェクトに実装されており、全てのオブジェクトはモデルとして動作する。つまりクラスオブジェクトもモデルとして使用できるようになっている。 は へと場を移し、表現と制御そして、表現対象となる情報を1個のオブジェクトで兼任する として再設計された。 によって発展した は に移植され系統の 環境で基本GUIシステムを構築している。 の はウェブブラウザ―のDOMや に大きな影響を与えている。
出典:wikipedia
LINEスタンプ制作に興味がある場合は、
下記よりスタンプファクトリーのホームページをご覧ください。