Learn AppleScriptObjC


Learn AppleScriptObjC


第3章 オブジェクト指向

home  前へ  次へ  mail


スクリプトオブジェクト

 スクリプトオブジェクトは、AppleScript における、オブジェクト指向プログラミングの要です。他のオブジェクト指向プログラミング言語のクラスやオブジェクトと言われるものがこれにあたります。一般的にオブジェクト指向プログラミングにとって必要な要件は次の3つに集約されると思います。

クラスとインスタンスという言葉が出てきましたが、多くのオブジェクト指向言語では、このうちインスタンスのみをオブジェクトとして捉えるもの多いようです。しかし 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 script

awakeFromNib() メソッドはやめて 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章からは再びデータの扱いについての学習を進めたいと思います。


home  前へ  次へ  mail


無断転載禁止
Copyright 2014. applescript.jp All right reserved.