今回は、いよいよクラスを定義する。ユーザーが定義するクラスは「カスタムクラス」と呼ぶ。カスタムクラスは、ActionScript定義済みのクラスと同じように使うことができる。Flashムービー(FLA)ファイルとは別のActionScript(AS)ファイルを作成して定義するので、他のプロジェクトに流用したり、ライブラリを構築するのに便利だ。
空のクラスをつくる
始めは、プロパティもメソッドもない空っぽのクラスを定義してみよう。それでも、インスタンスは作成できる。DateやArrayクラスのインスタンスは、new演算子を使ってつぎのように生成した。カスタムクラスのインスタンスも、また同じようにつくる。
カスタムクラスを定義するには、まずActionScript(AS)ファイルを開かねばならない。[ファイル]メニューから[新規]で[新規ドキュメント]ダイアログボックスを開き、[ActionScript(AS)ファイル]を選ぶ(図1)。
そのクラス名を用いて、新規ActionScript(AS)ファイルがスクリプトウィンドウで開く。クラス定義はこのスクリプトウィンドウに記述して(図2)、Flashムービー(FLA)ファイルとは別に保存する。
クラス定義には作法がある。まず、クラス名を識別子で決める。すると、プロパティやメソッドのない最小限のクラスは、つぎのように定義する。
クラスはclass定義キーワードに続けて、クラス名を指定して定義する。そして、続く中括弧{}内のクラス本体には、プロパティやメソッドが記述される。さらに、そのクラス全体をpackageという定義キーワードと中括弧{}で括るのだ。packageキーワードの後には、オプションとしてパッケージ名を指定することもできる(省略可能)。
クラス本体には、プロパティをvar宣言し、メソッドはfunctionとして定義する。その基本は、フレームアクションに変数を宣言したり、関数を定義するのと変わらない。
ところで、前掲「最小限のクラス定義」には、クラスと同名のfunction、つまりメソッドが定義されている。これは、「new クラス名()」でインスタンスを生成するときに呼出される特別なメソッドだ。「コンストラクタ」または「コンストラクタメソッド」という。
クラスを定義すると、クラス名は都合3箇所で使われる。第1に、文字どおりクラス名だ。第2に、コンストラクタメソッド名に、そのクラス名が使われる。そして第3に、クラスを定義したActionScript(AS)ファイルは、「クラス名.as」という名前で保存しなければならない。
- クラス名が指定される3箇所
- クラス名
- コンストラクタメソッド名
- ActionScript(AS)ファイル名
それでは、上述の作法に則って、プロパティも(コンストラクタは別にして)メソッドももたない空っぽのクラスMyClassを、以下のように定義してみよう。なお、コンストラクタメソッドはクラスのインスタンスを返すが、戻り値(returnステートメント)とそのデータ型は指定しないことに注意してほしい[1]。
保存するActionScriptファイル名は、「MyClass.as」だ。保存先は、パッケージ(package)の指定などによっても変わる。今回は指定なしなので、このクラスを使うFlashムービー(FLA)ファイルと同じ場所に保存する。
これで、最小限のクラス定義はできた。同じ場所に保存した Flashムービー(FLA)ファィルのフレームアクションからクラスMyClassのコンストラクタをつぎのように呼出せば、インスタンスが作成されそうに思える。しかし、実際には[コンパイルエラー]が発生してしまう(図3)。
実は、クラスには、そのクラスにアクセスできる範囲が指定できる。これはmixi日記などで、その公開範囲を決められるのに似ている。Flashムービーファイルのフレームアクションからアクセスするには、そのクラスは「全体に公開」を意味するpublicという属性が指定されていなければならないのだ。この属性はclassキーワードの前に記述する(スクリプト1)。
[ムービープレビュー]を見ると、クラスMyClassのインスタンスが生成され、[出力]ウィンドウに「[object MyClass]」と表示される(図4)(※2)。なお、クラス定義を修正したら、必ず保存しなければならない。SWFを書出す(コンパイルする)とき、Flashは保存されたActionScriptファイルからクラス定義を読込むからだ[3]。スクリプトウィンドウで書替えただけでは、その修正はSWFファイルに反映されないので注意しよう。
プロパティとメソッドを定義する
それでは新たなクラスを定義して、簡単なプロパティとメソッドを加えてみよう。クラス名はMyTimerとし、getTimer()関数と同じような、経過時間が調べられるメソッドを備える。時間のスタートは、クラスMyTimerのインスタンスを生成したときとする。
そして、MyTimerクラスにメソッドgetElapsedTime()を定義して、インスタンスが生成されてから経過した時間をミリ秒で返そう。関数を定義する場合と同じく、クラスの定義も、その利用の仕方から考えるとデザインしやすい。
すると、インスタンスが生成された時刻を、プロパティに保持しておく必要がありそうだ。そのプロパティ名はmy_dateとし、コンストラクタメソッドが呼出されたときに、Dateインスタンスを生成して代入する。他方、getElapsedTime()は、呼出されたときに新たなDateインスタンスを生成する。そのうえで、そのDateインスタンスとプロパティmy_dateのDate.timeプロパティ値の差を取れば、経過ミリ秒数は計算できる。
以上の考え方で定義したクラスMyTimerが、つぎのスクリプト2だ。
処理の内容そのものは、上記の説明で十分だろう。ここで解説を加えたいのは、var宣言やfunction定義の前につけたアクセス制御の属性privateおよびpublicである。
これらはclass定義キーワードの前に添えたpublic属性と同じく、プロパティやメソッドに対して、どこからのアクセスを認めるかという、いわば公開範囲の指定だ。publicは、classで説明したとおり、すべてのクラスやタイムラインからのアクセスを許す。したがって、メソッドgetElapsedTime()は、フレームアクションから呼出すことができる。privateはもっとも閉鎖的な指定で、それを宣言・定義したクラス内からしかアクセスできない(表1)(※4)。
表1 アクセス制御の属性キーワード(一部)
アクセス制御の属性 |
説明 |
private |
定義されたクラス内からのみ、アクセスすることができる。 |
public |
任意のクラスやタイムラインから、アクセスすることができる。コンストラクタメソッドは、このpublic属性しか指定できない。 |
たとえば、フレームアクションからMyTimerインスタンスに対して、privateプロパティmy_dateにつぎのようにアクセスしようとすれば、[コンパイルエラー]が生じる(図5)。private属性を指定したプロパティは、外部から直接値を取得・設定されないことが保障されるのだ。
メソッドgetElapsedTime()はpublic属性の指定なので、もちろんフレームアクションから呼出せる[5]。テスト用につぎのようなフレームアクションを記述すれば、ステージをクリックするたびに、MyTimerインスタンスを生成してから経過した時間がミリ秒で[出力]パネルに表示される[6]。
これで、ごく単純なクラスが定義できた。次回は、このクラス定義に、もう少し手を加えてみることにしよう。
今回解説した次のサンプルファイルがダウンロードできます。