メッセージ
SenseTalkは、あるオブジェクトから別のオブジェクトに_メッセージ_を送信することで動作するオブジェクト指向言語です。メッセージがオブジェクトに送信されると、そのスクリプトにそのメッセージの_ハンドラ_がある場合、応答することができます。特定のメッセージのハンドラを持っていないオブジェクトは、そのメッセージを他のオブジェクトに引き渡します。ハンドラの使用方法の詳細は、ハンドラをご覧ください。
オブジェクトが_何かを行う_のは、_メッセージ_を受け取った時だけです。オブジェクトは自己にメッセージを送信することも、他のオブジェクトやスクリプトが存在する環境から送信されることもあります。例えば、スクリプトがコマンドラインから呼び出されると、スクリプトの名前に基づいたメッセージが送信され、スクリプトが実行されます。
最初に知っておくべきことは、メッセージがオブジェクトに送信された時、それを受け取って処理することも無視することもできる、ということです。メッセージとその送信方法については、引き続きお読みください。
メッセージの送信
スクリプトが実行されているとき、コマンドを実行するたびにメッセージが送信されます。メッセージは常に単語であり、最も単純なメッセージ送信文は単語一つのコマンドで、送信されるメッセージの名前です。例えば、このスクリプトの2行目は、"greetTheUser"というメッセージを送信します。
put "Hello, World!"
greetTheUser
put farewellMessage()
このスクリプトでは、1行目と3行目のput
コマンドもメッセージを送信します。実際、SenseTalkの基本的な制御構造を除いて、スクリプトのほぼすべてのコマンドがメッセージを送信します。上記の“farewellMessage()”関数への呼び出しのような関数呼び出しも、メッセ出しもメッセージを送信します。
コマンドメッセージと関数メッセージ
SenseTalkは実際には2種類のメッセージを送信します。コマンドメッセージはコマンドによって送信され、上述の例のgreetTheUser
のようなものです。関数メッセージは関数呼び出しによって送信され、上述の例のfarewellMessage()
のようなものです。2つのメッセージタイプは、それらを受け取るハンドラのタイプを除いて同一です(ハンドラを参照)。関数の呼び出し方についての詳細は、関数を参照してください。コマンドの使用方法についての詳細は、コマンドとコメントを参照してください。
メッセージはどこに送信されるのか?
私たちは先ほど、メッセージはオブジェクトがお互いに通信するために使われると述べましたので、上記の"greetTheUser"と"put"メッセージはどこに送信されるのか、どのオブジェクトがこれらのメッセージを受け取るのか、疑問に思うかもしれません。答えは非常に シンプルで、多少驚くかもしれませんが、これらのコマンドを含むオブジェクトはこれらのメッセージを自身に送信します!
初めてみると、オブジェクトが自身にメッセージを送信することはあまり役に立たないように思えるかもしれませんが、実際にはオブジェクトが処理しない任意のメッセージは、他のオブジェクトが可能性として処理したり、最終的にはSenseTalkの組み込みコマンドや関数のいずれかが処理したりします。
必要に応じて、メッセージを他の特定のオブジェクトに直接送信することもできます。これは、tell
コマンド、send
コマンド、run
コマンド、run
関数、角括弧メッセージ構文 を使用したり、of
、.
または 's
を以下のように使用することで実現します:
put the salary of writer into authorPay -- "salary" を writer に送信する
get investor's balance("Checking") -- "balance" を investor に送信する
add paycheck.netIncome() to it -- "netIncome" メッセージを paycheck に送信する
メッセージパス
メッセージがオブジェクトに送信されると、そのメッセージはいくつかの異なるオブジェクトを通るパスを辿ります。メッセージが辿るパス上の各オブジェクトは、そのメッセージを処理するチャンスが与えられます。オブジェクトにそのメッセージのハンドラがある場合、そのハンドラの指示が実行されます。それ以外の場合、メッセージは、メッセージを処理するものが見つかるまで、順番にパス上の他のすべてのオブジェクトに提供されます。
通常、メッセージがオブジェクトによって処理されると、それで終わりです。しかし、場合によっては、オブジェクトのハンドラがメッセージをパスに沿って送り続けることを選択することがあり、他のオブジェクトが同じメッセージを処理する機会を得ることがあります(メッセージのパスの pass
コマンドを参照)。
バックスクリプトとフロントスクリプト
全体像を見てみると、メッセージが送信されるオブジェクト(ターゲットオブジェクトと呼ばれる)に加えて、メッセージパスはターゲットオブジェクトとそのヘルパーの前後に他のオブジェクトも含むことがあります。これらのインクルードは、the FrontScripts
と the BackScripts
のオブジェクトと、ホストアプリケケーションが追加する可能性のある他のオブジェクトで構成されています。
The BackScripts
は、ターゲットオブジェクトがメッセージを処理しなかった場合に、メッセージを処理する機会を得るオブジェクトのリストを含むグローバルプロパティです。したがって、オブジェクト(ライブラリやスクリプト)を the BackScripts
に挿入することで、そのオブジェクトのハンドラが任意のスクリプトで利用可能になり、それでも任意の個別のスクリプトが the BackScripts
の振る舞いをオーバーライドするための自分自身のハンドラを提供することを許します。 The BackScripts
は非常に便利なメカニズムであるため、Start Using
とStop Using
の二つの特別なコマンドが、the BackScripts
にオブジェクトを追加したり削除したりするのを簡単にするために提供されています。
The FrontScripts
は、ターゲットオブジェクトがメッセージを提供される前にメッセージを処理する機会を得るオブジェクトのリストを含む、まれにしか使用されないグローバルプロパティです。これにより、これらのオブジェクトはメッセージをインターセプトし、メッセージをメッセージパスに沿ってパスする前にメッセージをログに記録するなどのタスクに対して、任意のオブジェクトの振る舞いをオーバーライドする可能性を持ちます。
Start Using
コマンド
振る舞い: スクリプトや他のオブジェクトを the BackScripts
に挿入します。これは insert <object> into the BackScripts
コマンドと同等ですが、よりシンプルで読みやすいです。
Syntax:
start using object
insert object into back
insert object into the BackScripts
例:
start using "Folder1/Helper1" // Puts Helper1 (from Folder1) into the BackScripts
関連項目:
Stop Using
コマンド
振る舞い: the BackScripts
に以前挿入されたライブラリやスクリプトを削除します。これは remove <object> from the BackScripts
コマンドと同等ですが、よりシンプルで読みやすいです。
Syntax:
stop using object
remove object from back
例:
stop using "Folder1/Helper1" // Removes Helper1 (of Folder1) from the BackScripts
関連項目:
ヘルパー
メッセージがパスをたどって各オブジェクトに渡されるとき、そのオブジェクトのスクリプトがメッセージのハンドラを含んでいるかどうかチェックされます。もし含んでいれば、そのハンドラが実行されます。そうでなければ、メッセージは順番にそのオブジェクトの各ヘルパーにも渡され、そのうちのどれかがメッセージのハンドラを持っているかどうかを確認します。ヘルパーが適切なハンドラを持っているかどうかを確認するとき、そのヘルパーのリストも参照され、またそのヘルパーのヘルパー(もしあれば)も参照されます。全てのヘルパーがチェックされて初めて、メッセージがメッセージパスの次のオブジェクトに渡されます。
the BackScripts
リストのオブジェクトは、メッセージパスの他のオブジェクトが処理しなかったメッセージだけを受け取ります。これらは通常、多くの異なるオブジェクトが必要とする可能性がある基本的な機能を提供するために使用されます。 the FrontScripts
リストのオブジェクトは、ターゲットオブジェクトに到達する前に任意のメッセージをインターセプトして処理する機会を得ます。この機能はまれにしか使用されませんが、特定の状況では強力になる可能性があります。
ホストアプリケーション
メッセージをパスするパスのすべてのオブジェクト(およびそのヘルパー)がそれを処理する機会を得た後、メッセージはホストアプリケーションとSenseTalk自体に配信されます。メッセージが組み込みのコマンドや関数に対応していれば、そのコマンドや関数が処理されます。一部のメッセージはSenseTalkに認識されますが無視されます。メッセージがSenseTalkによって認識されて処理されず、また認識されて無視されない場合、ホストアプリケーションはメッセージと同じ名前のスクリプトファイルを探します。通常、少なくとも呼び出しスクリプトが存在する同じフォルダを見ますし、他のフォルダも見る可能性があります。スクリプトファイルがメッセージを処理するために見つけられない場合、エラーが発生します。
完全なメッセージパス
メッセージがオブジェクト(ターゲットオブジェクトとして知られる)に送信されると、メッセージの完全なパスには以下のオブジェクトが含まれます、この順序で:
the FrontScripts
に挿入された順序でのオブジェクト(最近挿入されたオブジェクトが最後にメッセージを受け取る)とそのヘルパー- ターゲットオブジェクトとそのヘルパー
the BackScripts
にあるオブジェクト(最近後ろに挿入されたオブジェクトが最後にメッセージを受け取る)とそのヘルパー- ホストアプリケーションとSenseTalk自体
- ホストアプリケーションによって特定されたフォルダの他のスクリプトファイル
メッセージのハンドラが見つかると、そのハンドラが実行されます。そのようなハンドラがメッセージを渡さない場合、それは処理され、これ以上進まないと考えられます。ただし、ハンドラは pass
コマンド(またはそのバリアント)を使用してメッセージを渡すことを選択することもあります。そうすると、メッセージは処理されていないかのようにメッセージのパスを続け、後続のオブジェクトがそのメッセージを受け取るチャンスを得ます。
ターゲット
メッセージはメッセージパス上のいくつかの異なるオブジェクトによって処理される可能性があるため、これらのオブジェクトはメッセージが送信されたオブジェクトを見つける必要があるかもしれません。これが the target
の目的で、ターゲットオブジェクトを特定します。たとえば、the BackScripts
に挿入されたオブジェクトは incrementAccessCount
ハンドラを持つかもしれません。このハンドラは、実行するたびにカウンタを増やします。次のようになります。
on incrementAccessCount
add 1 to the accessCount of the target
end incrementAccessCount
ここでは、自身の accessCount
プロパティに単一のカウンタを維持するのではなく、incrementAccessCount
メッセージを受け取ったオブジェクトの accessCount
プロパティを更新しています。