2010-04-12T18:01:47+09:00

スクリプトオブジェクトのハンドラを入れ替えてみる

AppleScript のハンドラの面白い?かもしれない性質を紹介します。

皆さん、AppleScript のハンドラは次のように、ハンドラを変数を介して実行することができることをごぞんじですか?

property _msg : "hello"
on msg()
return my _msg
end msg

set a_handler to msg
a_handler() -- result : "hello"

こんなことができると、柔軟なスクリプトが組めていいことがあるんじゃないか〜と思うかもしれないけど、実はそんなに使えるテクニックじゃない。

なんでかというと、ハンドラはローカル変数やハンドラの引数に渡しても実行できないから。global 変数、run ハンドラ内の変数に設定してもトップレベルのスクリプトからしか呼べない。実質的に、ハンドラは property に設定しないと実行できない(property 以外に設定した場合の振る舞いについては、また今度)。

これはごもっともで、どうしようもない制限だと思う。なんでかというと、ハンドラの中で my property_name (my は省略可能なこともある)というように、property を参照できるけど、ローカル変数にいるハンドラには my で示しているスクリプトオブジェクトがどれか分からない。つまり、ハンドラは常にどこかのスクリプトオブジェクトに所属していなくちゃいけないんだ。

AppleScript のハンドラは関数ではなく、オブジェクトに結びつけられているメソッドだということか。

だから、AppleScript では変数経由で実行するコードを渡したい場合は、スクリプトオブジェクトを単位にすることになる。でも、こんな定石を無視してハンドラで遊んでみる。

ということを試してみた。

script ScriptB
property _msg : "I'm b"
property _name : "b"
property msg : missing value
end script

script ScriptA
property _name : "a"
property _msg : "I'm a"

on msg()
return my _msg
end msg
end script


set ScriptB's msg to ScriptA's msg
log ScriptB's msg() -- result : "I'm b"

期待通りに動作してくれているようだ。

でも、property _msg を参照をするところの my をはずしてみる。

script ScriptB
property _msg : "I'm b"
property _name : "b"
property msg : missing value
end script

script ScriptA
property _name : "a"
property _msg : "I'm a"

on msg()
return _msg
end msg
end script


set ScriptB's msg to ScriptA's msg
log ScriptB's msg() -- result : "b"

すると、なんかうまくいかない。property を名前ではなく定義順で参照しちゃっているようだ。

property の参照には、いつも my をつけるのが吉、ということでしょうか。