ヘルパー
SenseTalkオブジェクトは単独で存在する必要はありません。他のオブジェクトが一部または全部の動作を補助(helped
)することが可能です。例えば、誕生日に基づいてその人の年齢を計算するハンドラーを持つ人物オブジェクトを作成した場合、その人物オブジェクトは他のオブジェクトのヘルパーとして使用でき、それらも年齢を計算することが可能になります。そのためには、それら自身のハンドラーは不要です。
以下に、RexとSueという名前の他の二つのオブジェクトによってヘルプされるオブジェクトのサンプルスクリプトを示します:
sayHello -- 最初に友好的な態度で始めましょう!
properties
helpers: [Rex, Sue],
birthdate: "May 14, 1942",
end properties
on sayHello
put "Greetings! My age is " & calculateAge()
end sayHello
このオブジェクトのsayHello
ハンドラーはcalculateAge
という名前の関数を呼び出します。sayHello
ハンドラーが呼び出されると、それはcalculateAge()
を呼び出します。このオブジェクトにはcalculateAge関数ハンドラーがありませんが、もしヘルパーの一つ、例えばRexがそのような関数ハンドラーを持っているなら、そのハンドラーはこのオブジェクトの代わりに実行され、年齢を計算します。
Who is Me? What is This Object?
オブジェクトとそのヘルパーは密接に連携し、まるで一つのオブジェクトのように動作します(三銃士のスローガン、「一人のために全員、全員のために一人」を思い浮かべてください)。ヘルパー内のハンドラーが実行されるとき、それは元のオブジェクトのハンドラーであるかのように扱われます。このコンテキストでは、me
とmy
はヘルパーではなく、ヘルプされるオブジェクトを指します。
これは、ヘルパーのスクリプト内で実行される任意のステートメントがそのメッセージをヘルプされるオジェクトにターゲットし(そして間接的にヘルパーに対して)、ヘルパーがme
またはmy
を使用してプロパティにアクセスするとき、ヘルプされるオブジェクトのプロパティにアクセスすることを意味します。スクリプトが自身をターゲットにするか、または自身のプロパティにアクセスする必要がある場合、me
の代わりにthis object
という用語が使われることがあります。
ヘルパーのメッセージパス内の位置
オブジェクトのヘルパーは、メッセージパス内でそのオブジェクトと密接に関連しています。オブジェクトがハンドラーを持っていないメッセージ(または取り扱ってからパスする)を受け取ると、そのメッセージは次にオブジェクトのヘルパーに行きます。ヘルパーがメッセージを取り扱わない場合のみ、メッセージはメッセージパス内の他のオブジェクト、たとえばbackScripts
内のオブジェクトにパスされます。
ヘルパーに設計されたオブジェクト
どのオブジェクトも、他の一つまたは複数のオブジェクトのヘルパーとなることができます。例えば、RexというオブジェクトがcalculateAge()
関数ハンドラーを持っていると仮定します。そして、同じcalculateAge()
機能が必要な別のオブジェクト、Lunaがあると仮定します。RexをLunaのヘルパーのリストに追加することで、Lunaはその能力を獲得します。しかし、Rexは他にもハンドラーを持っているかもしれません。それら全てがLunaの行動の一部として含まれることが望ましいわけではありません。Lunaが必要とする機能だけをどのように提供することができるでしょうか?
このような状況に対処する一つの良い方法は、複数の異なるオブジェクトに有用かもしれないその行動(ハンドラー)を分け出し、特にヘルパーとしての役割を果たすために設計された新しいオブジェクトを作成 することです。例えば、calculateAge()
ハンドラーをRexからPersonオブジェクトに移動し、それからPersonをRexとLunaのヘルパーリストに追加するかもしれません。各オブジェクトは任意の数のヘルパーを持つことができますので、関連する行動のグループをヘルパーオブジェクトに分け出すことは非常に強力なツールとなります。それにより、異なるオブジェクトでその機能をさまざまな組み合わせで再利用することが可能となります。
ヘルパーとなるオブジェクトの設計
多くのヘルパーオブジェクトは非常にシンプルで、数個のハンドラーを持つスクリプトだけを持っています。例えば、Personオブジェクトは、私たちが話してきたcalculateAge()
関数のような単一のハンドラーで始まるかもしれません:
to calculateAge -- returns my current age in years
return (the date - my birthDate) / 365.25 days
end calculateAge