Learn AppleScriptObjC
スクリプトオブジェクト スクリプトオブジェクトは、AppleScript における、オブジェクト指向プログラミングの要です。他のオブジェクト指向プログラミング言語のクラスやオブジェクトと言われるものがこれにあたります。一般的にオブジェクト指向プログラミングにとって必要な要件は次の3つに集約されると思います。
- プロパティ (propety、属性)と、それを操作するメソッド (method、手続き) を持っていること
- 他のクラスのすべてのプロパティとメソッドを継承した、新しいクラスが作れ、その新しいクラスに、さらにプロパティやメソッドを追加することができること
- クラスという設計図 (ヒナ型)から、複数のインスタンス (instance、実体) をいくつでも作れ、各インスタンスの属性に固有の値を設定できること
クラスとインスタンスという言葉が出てきましたが、多くのオブジェクト指向言語では、このうちインスタンスのみをオブジェクトとして捉えるもの多いようです。しかし Objective-C では、クラスとインスタンスの両方がオブジェクトとして考えられています。このふた通りの考え方の違いは、
「クラスがメソッドに応えられるかどうかによって区別されている」
と考えて良さそうです。つまりクラスとインスタンスの両方がメソッドの呼び出しに応答できる場合は、この両方をオブジェクトとみなし、インスタンスのみがメソッドの呼び出しに応答できる場合は、インスタンスのみをオブジェクトとみなすということです。ただしクラスは、最低でも「インスタンスを作る」というメソッドに応えられなければいけないのは当然のことです。
前置きが長くなりましたが、AppleScript のスクリプトオブジェクトは、第1の要件と、第2の要件は満たしています。つまり、プロパティとメソッドを持つことができ、他のクラスを継承することができます。ただし、第3の要件である、複数のインスタンスを作って、それぞれのプロパティに固有の値を設定することができません。
このことを知った時には正直凹みました。知ったのは本日2014年10月22日でしたが。
この、複数のインスタンスに、固有の値を持たせることができないことが、どう問題かと言うと、まずはデータです。例えば会員名簿などを作るとします。それぞれの会員の住所・氏名・生年月日・職業などを登録します。その会員データはのヒナ型として「会員」クラスを作ったとします。そしてその「会員」クラスからおのおのの会員の「会員」インスタンスを作り、それぞれの住所・氏名などにそれぞれのデータを入れる。ということができないわけです。
この AppleScript の短所とも言えることの解決策を、ネットで色々調べました。しかし、私のコーディングが悪いのか、安定的に使える手法は見つかりませんでした。スクリプトオブジェクトのプロパティの扱いが非常に難しいからです。そこで少し考えを変えてみました。
「プロパティを持たない、メソッドだけのクラス (スクリプトオブジェクト) を作ればどうだろうか」と
Fortunes 再び 説明が長くなりましたが、同じクラスの複数のインスタンスが必要になる可能性が一番高いのは、前節でも説明したようにデータのひな型となるクラスです。ここでは、前章で作成した Fortunes をさらに拡張しながら例を示していきたいと思います。Fortunes は GUI を持たないアプリケーションですが、あなたの Fortune (運勢) を10日分予想して
「○月○日のラッキーカラーとラッキーナンバーは○○と○○です」と表示します。
そして、Fortunes は、その表示するデータを作成するためのクラスを持っています。このように同種のデータ (会員名簿もその一つです) が必要となる場合は、モデル (model、データ用のオブジェクトを表すコンピュータ用語) と呼ばれるクラスを作り、そのクラスから各データ用に インスタンスを作ります。(例えば、会員一人一人のために、あるいは各週の宝くじの当たり予想番号ために)では、前節で作成した Fortunes プロジェクトの Fortune.applescript を次のように書き換えてください。赤色の箇所が追加・変更された部分です。
Fortune.applescript
script Fortune property parent : class "NSObject" on makeFortune_(i) set col1 to some item of {"Purple", "Navy", "Brown", "Green"} set num2 to random number 9 set date1 to current date repeat i times set date1 to date1 + days end repeat set fortune to {colVal:col1, numVal:num2, entryDate:date1} return fortune end makeFortune_ end scriptawakeFromNib() メソッドはやめて makeFortune_() という新しいメソッドを作っています。awakeFromNib() は MainMenu.xib がロードされた時に呼び出されますが、今回の makeFortune_() は、AppDelegate.applescript から呼び出します。
コード説明
- 3行目: on makeFortune_(i)
- makeFortune というメソッドを宣言しています。このメソッドはパラメーター (parameter、引数) を一つ受け取ります。
- 4行目:set col1 to some item of {"Purple", "Navy", "Brown", "Green"}
- "Purple"、"Navy"、"Brown"、"Green" という4つの文字列から構成されたリストから some item of でランダムに取得した文字列を col1 変数に代入しています。some キーワードは、このように、random number の代わりに使うこともできて便利です。また random numbet よりも処理が早いとの話しもあります(事実未確認です)。
- 5行目:set num2 to random number 9
- AppleScript の random number コマンドを使って 0 〜 9 のランダムな数値を作り、その値を num2 に代入しています。
- 6行目:set date1 to current date
- AppleScript の current date コマンドを使って、現在の日時データを date1 に代入しています。
- 7行目:repeat i times
- makeFortune_() メソッドの引数として受け取った i 回、繰り返しを行うという意味です。
- 8行目: set date1 to date1 + days
- date1 (現在日時) に AppleScript の days キーワードで得られる 86400 秒を足しています。86400 秒は 24 時間になります。結果として、丸一日後の日時データが date1 に代入されます。
- 9行目: end repeat
repeat で始まる繰り返し文は、必ず end repeat で終わらせなければなりません。 なお、7行目から9行目をまとめて、set date1 to date1 + days * i とすることもできます。というか、本来は、このコードのほうが正解です。繰り返し文を記述する必要もありません。しかし、なぜか OS X Yosemite と Xcode 6.1 の組み合わせでは、set date1 to date1 + days * i がエラーになるので、繰り返し文を使うことにいたしました。- 10行目: set fortune to {colVal:col1, numVal:num2, entryDate:date1}
- 前行までで作成した、col1 と、num2と、date1 に、それぞれ colVal、numVal、entryDate という名前を付けて、レコードを作っています。そして、そのレコードを、fortune という変数に代入しています。レコードとは、それぞれのデータを、名前をで区別する、コレクション・データです。そして、この名前のことをキー (key) といい、コーディングは次のようになります。なお、このレコードのことを、他のプログラミング言語では辞書 (dictionary) や、連想配列といいます。
{ key1 : data1, key2 : data2, key3 : data2 } - 11行目: return fortune
- makeFortune_() メソッドの呼び出し元へ、fortune レコードを返しています。
- 12行目: end makeFortune_
- on someMethod で作成したメソッドは、必ず end someMethod で終わらせなければなりません。
スクリプトオブジェクトを使う 次に、AppDelegagte.applescript も次ように書き換えます。赤色の部分が追加・変更された箇所になります。
AppDelegate.applescript
property Fortune : class "Fortune" script AppDelegate property parent : class "NSObject" -- IBOutlets property theWindow : missing value on applicationWillFinishLaunching_(aNotification) -- Insert code here to initialize your application before any files are opened set fortunes to {} set i to 0 repeat 10 times set fortunes to fortunes & makeFortune_(i) of Fortune set i to i + 1 end repeat set i to 1 repeat 10 times set fortune to item i of fortunes set date1 to entryDate of fortune set str1 to text 1 thru 3 of (month of date1 as text) & " "¬ & text -2 thru -1 of ("0" & day of date1 as text) & " = "¬ & text 1 thru 6 of (colVal of fortune & " ") & " and "¬ & (numVal of fortune) as text log str1 set i to i + 1 end repeat end applicationWillFinishLaunching_ on applicationShouldTerminate_(sender) -- Insert code here to do any housekeeping before your application quits return current application's NSTerminateNow end applicationShouldTerminate_ end script
コード説明
- 1行目: property Fortune : class "Fortune"
- スクリプトオブジェクト (クラス) に、スクリプトオブジェクト (クラス) を読み込むには、このように記述します。記述する場所は、スクリプトオブジェクト (script someClass) が、始まるより前に記述します。
- 8行目:set fortunes to {}
- fotunes という、空のリストを作成しています。データがコレクションである場合は、変数名に s を付けて、複数形にする命名規則を使っています。この命名規則は、Objective-C で一般的に使われている方法です。
- 9行目:set i to 0
- i という変数に 0 という整数値を代入しています。
- 10行目:repeat 10 times
- これから 10 回の繰り返しがはじまることを宣言しています。
- 11行目:set fortunes to fortunes & makeFortune_(i) of Fortune
- この AppDelegate スクリプトファイル の先頭で読み込んだ、Fortune スクリプトオブジェクト (Fortune クラス) の makeFortune_() メソッドを、変数 i の値を引数として渡し呼び出しています。そして戻ってくる値を、fortunes リストの最後に追加しています。
- 12行目: set i to i + 1
- 変数 i の値を 1 増やしています。
- 13行目: end repeat
repeat で始まる繰り返し文は、必ず end repeat で終わらせなければなりません。 - 14行目: set i to 1
- 変数 i の値を 1 にしています。
- 15行目: repeat 10 times
- 10 回の繰り返しがはじまること宣言しています。
- 16行目: set fortune to item i of fortunes
- リスト fortunes から i 番目のデータを取り出し、forutune 変数に代入しています。変数名に複数形を表す s が付いているかいないかに注意してください。
- 17行目: set date1 to entryDate of fortune
- fortune 変数に収められている Fortune レコードから、entryDate キーの値を取り出しています。そしてその値を変数 date1 に収めています。
- 18行目〜21行目: set str1 to text 1 thru 3 of (month of date1 as text) & " " ¬
& text -2 thru -1 of ("0" & day of date1 as text) & " = " ¬
& text 1 thru 6 of (colVal of fortune & " ") & " and " ¬
& (numVal of fortune) as text
- ¬ 記号を使って改行していますが、実際には一行のコードです。ログとして出力するためのテキストデータを作成して、変数 str1 に収めています。詳しくは、後日掲載する AppleScript のサイトで説明いたします。
- 19行目: log str1
- 変数 str1 の文字列を、ログとして出力しています。
- 20行目: set i to i + 1
- 変数 i の値を 1 増やしています。
- 21行目: end repeat
- repeat キーワードではじめた繰り返し文は、必ず end repeat で終了しなければなりません。
実行結果
第3章の終わりに 次章では、ちょっとした息抜きがわりとして、かんたんな Web ブラウザを作ってみようと思います。そして、第5章からは再びデータの扱いについての学習を進めたいと思います。
無断転載禁止
Copyright 2014. applescript.jp All right reserved.