ActionScript 3.0で始めるオブジェクト指向スクリプティング

第18回カスタムクラスを定義する

今回は、いよいよクラスを定義する。ユーザーが定義するクラスは「カスタムクラス」と呼ぶ。カスタムクラスは、ActionScript定義済みのクラスと同じように使うことができる。Flashムービー(FLA)ファイルとは別のActionScript(AS)ファイルを作成して定義するので、他のプロジェクトに流用したり、ライブラリを構築するのに便利だ。

空のクラスをつくる

始めは、プロパティもメソッドもない空っぽのクラスを定義してみよう。それでも、インスタンスは作成できる。DateやArrayクラスのインスタンスは、new演算子を使ってつぎのように生成した。カスタムクラスのインスタンスも、また同じようにつくる。

var 変数:クラス = new クラス名([引数])

カスタムクラスを定義するには、まずActionScript(AS)ファイルを開かねばならない。[ファイル]メニューから[新規]で[新規ドキュメント]ダイアログボックスを開き、[ActionScript(AS)ファイル]を選ぶ図1⁠。

図1 [新規ドキュメント]ダイアログボックスから[ActionScript(AS)ファイル]を選択
図1 [新規ドキュメント]ダイアログボックスから[ActionScript(AS)ファイル]を選択

そのクラス名を用いて、新規ActionScript(AS)ファイルがスクリプトウィンドウで開く。クラス定義はこのスクリプトウィンドウに記述して図2⁠、Flashムービー(FLA)ファイルとは別に保存する。

図2 クラス定義はスクリプトウィンドウに記述
図2 クラス定義はスクリプトウィンドウに記述

クラス定義には作法がある。まず、クラス名を識別子で決める。すると、プロパティやメソッドのない最小限のクラスは、つぎのように定義する。

最小限のクラス定義
最小限のクラス定義

クラスはclass定義キーワードに続けて、クラス名を指定して定義する。そして、続く中括弧{}内のクラス本体には、プロパティやメソッドが記述される。さらに、そのクラス全体をpackageという定義キーワードと中括弧{}で括るのだ。packageキーワードの後には、オプションとしてパッケージ名を指定することもできる(省略可能⁠⁠。

クラス本体には、プロパティをvar宣言し、メソッドはfunctionとして定義する。その基本は、フレームアクションに変数を宣言したり、関数を定義するのと変わらない。

ところで、前掲「最小限のクラス定義」には、クラスと同名のfunction、つまりメソッドが定義されている。これは、⁠new クラス名()」でインスタンスを生成するときに呼出される特別なメソッドだ。⁠コンストラクタ」または「コンストラクタメソッド」という。

クラスを定義すると、クラス名は都合3箇所で使われる。第1に、文字どおりクラス名だ。第2に、コンストラクタメソッド名に、そのクラス名が使われる。そして第3に、クラスを定義したActionScript(AS)ファイルは、⁠クラス名.as」という名前で保存しなければならない。

クラス名が指定される3箇所
  1. クラス名
  2. コンストラクタメソッド名
  3. ActionScript(AS)ファイル名

それでは、上述の作法に則って、プロパティも(コンストラクタは別にして)メソッドももたない空っぽのクラスMyClassを、以下のように定義してみよう。なお、コンストラクタメソッドはクラスのインスタンスを返すが、戻り値(returnステートメント)とそのデータ型は指定しないことに注意してほしい[1]⁠。

package {
  class MyClass {
    function MyClass() {
    }
  }
}

保存するActionScriptファイル名は、⁠MyClass.as」だ。保存先は、パッケージ(package)の指定などによっても変わる。今回は指定なしなので、このクラスを使うFlashムービー(FLA)ファイルと同じ場所に保存する。

これで、最小限のクラス定義はできた。同じ場所に保存した Flashムービー(FLA)ファィルのフレームアクションからクラスMyClassのコンストラクタをつぎのように呼出せば、インスタンスが作成されそうに思える。しかし、実際には[コンパイルエラー]が発生してしまう図3⁠。

trace(new MyClass());
図3 クラスのコンストラクタを呼出すとコンパイルエラー発生
図3 クラスのコンストラクタを呼出すとコンパイルエラー発生

実は、クラスには、そのクラスにアクセスできる範囲が指定できる。これはmixi日記などで、その公開範囲を決められるのに似ている。Flashムービーファイルのフレームアクションからアクセスするには、そのクラスは「全体に公開」を意味するpublicという属性が指定されていなければならないのだ。この属性はclassキーワードの前に記述するスクリプト1⁠。

スクリプト1 public属性の指定されたクラスMyClassの定義
// ActionScript 3.0クラス定義ファイル: MyClass.as
package {
  public class MyClass {   // コンストラクタメソッド
    function MyClass() {
    }
  }
}

[ムービープレビュー]を見ると、クラスMyClassのインスタンスが生成され、[出力]ウィンドウに「[object MyClass]」と表示される図4※2⁠。なお、クラス定義を修正したら、必ず保存しなければならない。SWFを書出す(コンパイルする)とき、Flashは保存されたActionScriptファイルからクラス定義を読込むからだ[3]⁠。スクリプトウィンドウで書替えただけでは、その修正はSWFファイルに反映されないので注意しよう。

図4 クラスのインスタンスが生成されて[出力]パネルに表示
図4 クラスのインスタンスが生成されて[出力]パネルに表示

プロパティとメソッドを定義する

それでは新たなクラスを定義して、簡単なプロパティとメソッドを加えてみよう。クラス名はMyTimerとし、getTimer()関数と同じような、経過時間が調べられるメソッドを備える。時間のスタートは、クラスMyTimerのインスタンスを生成したときとする。

var myObject:MyTimer = new MyTimer();

そして、MyTimerクラスにメソッドgetElapsedTime()を定義して、インスタンスが生成されてから経過した時間をミリ秒で返そう。関数を定義する場合と同じく、クラスの定義も、その利用の仕方から考えるとデザインしやすい。

var nTime:Number = myObject.getElapsedTime();
trace(nTime);   // 出力: 経過ミリ秒

すると、インスタンスが生成された時刻を、プロパティに保持しておく必要がありそうだ。そのプロパティ名はmy_dateとし、コンストラクタメソッドが呼出されたときに、Dateインスタンスを生成して代入する。他方、getElapsedTime()は、呼出されたときに新たなDateインスタンスを生成する。そのうえで、そのDateインスタンスとプロパティmy_dateのDate.timeプロパティ値の差を取れば、経過ミリ秒数は計算できる。

以上の考え方で定義したクラスMyTimerが、つぎのスクリプト2だ。

スクリプト2 プロパティとメソッドを定義したクラスMyTimer
// ActionScript 3.0クラス定義ファイル: MyTimer.as
package {
  public class MyTimer {
    private var my_date:Date;
    public function MyTimer() {
      my_date = new Date();
    }
    public function getElapsedTime():Number {
      var current_date:Date = new Date();
      var nElapsedTime:Number = current_date.time-my_date.time;
      return nElapsedTime;
    }
  }
}

処理の内容そのものは、上記の説明で十分だろう。ここで解説を加えたいのは、var宣言やfunction定義の前につけたアクセス制御の属性privateおよびpublicである。

これらはclass定義キーワードの前に添えたpublic属性と同じく、プロパティやメソッドに対して、どこからのアクセスを認めるかという、いわば公開範囲の指定だ。publicは、classで説明したとおり、すべてのクラスやタイムラインからのアクセスを許す。したがって、メソッドgetElapsedTime()は、フレームアクションから呼出すことができる。privateはもっとも閉鎖的な指定で、それを宣言・定義したクラス内からしかアクセスできない表1※4⁠。

表1 アクセス制御の属性キーワード(一部)
アクセス制御の属性 説明
private 定義されたクラス内からのみ、アクセスすることができる。
public 任意のクラスやタイムラインから、アクセスすることができる。コンストラクタメソッドは、このpublic属性しか指定できない。

たとえば、フレームアクションからMyTimerインスタンスに対して、privateプロパティmy_dateにつぎのようにアクセスしようとすれば、[コンパイルエラー]が生じる図5⁠。private属性を指定したプロパティは、外部から直接値を取得・設定されないことが保障されるのだ。

var myObject:MyTimer = new MyTimer();
trace(myObject.my_date);   // コンパイルエラー
図5 private属性のプロパティに外部からアクセスすると[コンパイルエラー]が発生
図5 private属性のプロパティに外部からアクセスすると[コンパイルエラー]が発生

メソッドgetElapsedTime()はpublic属性の指定なので、もちろんフレームアクションから呼出せる[5]⁠。テスト用につぎのようなフレームアクションを記述すれば、ステージをクリックするたびに、MyTimerインスタンスを生成してから経過した時間がミリ秒で[出力]パネルに表示される[6]⁠。

var myObject:MyTimer = new MyTimer();
trace(myObject);   // 出力: [object MyTimer]
stage.addEventListener(MouseEvent.CLICK, xTrace);
function xTrace(eventObject:MouseEvent):void {
  var nElapsedTime:Number = myObject.getElapsedTime();
  trace(nElapsedTime);
}
図6 [出力]パネルにMyTimerインスタンスと経過ミリ秒数が表示
図6 [出力]パネルにMyTimerインスタンスと経過ミリ秒数が表示

これで、ごく単純なクラスが定義できた。次回は、このクラス定義に、もう少し手を加えてみることにしよう。

今回解説した次のサンプルファイルがダウンロードできます。

おすすめ記事

記事・ニュース一覧