サイトトップ

Director Flash 書籍 業務内容 プロフィール

Macromedia Flash非公式テクニカルノート

ActionScript 3.0でプライベートなコンストラクタを定義する

ID: FN0609001 Product: Flash

Platform: All
Version: Flash 9 (public alpha) and above

ActionScript 3.0では、プライベートなコンストラクタ関数を定義することができません。本稿では、まずActionScript 3.0のコンストラクタ関数について、簡単に説明します。つぎに、プライベートなコンストラクタ定義が必要な例として、デザインパターンのSingletonをどう実装するか考えてみたいと思います。

なお、クラスやActionScript 3.0の基礎知識を前提とします。ActionScript 3.0の基本については、Adobe Flashデベロッパーセンター「ActionScript 3.0書き方教室」をご参照ください。

1. コンストラクタ関数
ActionScript 3.0のクラスは、つぎのようなスタイルで定義します[*1]。クラス本体に定義される、クラスと同名の特別な関数が「コンストラクタ」です。

// ActionScript 3.0クラス定義ファイル: クラス名.as
package [パッケージ名] {
  class クラス名 {
    // プロパティ(変数)宣言
    function クラス名() {   // コンストラクタ関数
      // インスタンス生成時の初期化処理
    }
    // メソッド(関数)定義
  }
}

コンストラクタ関数は、インスタンスが作成されるときに呼出されます。したがって、初期設定の処理を記述することが通常です。コンストラクタの引数は、必要があれば指定します。ActionScript 3.0では、定義した引数の型だけでなく、その数が呼出しと一致しない場合にもコンパイルエラーになります。また、コンストラクタ関数には、戻り値は指定できません。

コンストラクタ関数は、最小限その本体ブロック({})内が空でも差支えありません。さらに、コンストラクタを定義しなくても、問題なくコンパイルされます。この場合、ActionScript 2.0では、「コンパイラによって空のコンストラクタ関数が自動的に作成され」ると説明されています。ActionScript 3.0でも、おそらく同様の内部処理になっているものと推測されます。しかし、この点について明記されたドキュメントは見当たりません[*2]

ActionScript 2.0との大きな違いとして、3.0ではコンストラクタ関数にはpublic属性のみ指定可能です。コンストラクタがクラス外から呼ばれないように、private属性を指定することはできないということです。しかし、実際上privateなコンストラクタ関数を定義したい場合はありえます。そこで、つぎにデザインパターンのSingletonを例に、その実装方法のひとつをご紹介します。

[*1] パッケージ名は、指定しないことも可能です。詳しくは、前出Adobe Flashデベロッパーセンター「ActionScript 3.0書き方教室」の「ActionScript 3.0クラス定義」をご参照ください。

[*2] akihiro kamijo「コンストラクタ(とSingleton)」およびそのコメントをご参照ください。

2. Singletonパターンの実装
ソフトウェア開発における「デザインパターン」という類型の中に、「Singleton」と呼ばれるパターンがあります[*3]。Singletonパターンでは、クラスからインスタンスはひとつしか作成できません。インスタンスを作成・取得する専用の静的(static)メソッドを用意し、クラスの外からはコンストラクタが呼出せない設計にします。

ActionScriptにおけるSingletonパターンのクラスには、SharedObjectがあります。SharedObjectクラスはコンストラクタを使わず、静的(static)メソッドSharedObject.getLocal()によりインスタンスを作成・取得します[*4]

ActionScript 2.0では、コンストタラクタ関数にprivate属性が指定できたので、クラス外から呼出されないようにすることは簡単でした[*5]。ActionScript 3.0では、残念ながらこの指定ができません。そこで以下のサンプル(スクリプト001)では、コンストラクタの呼出しが内部からであることを示すフラグにより、クラス外からの呼出しを回避する手法を採っています。

クラス内部からの呼出しであることを示すフラグは、静的(static)プロパティとして設定しました。コンストラクタは、そのプロパティが内部呼出しを示さないときは、エラーを生成(throw)します。インスタンスを取得・生成する静的メソッドは、メソッド内からコンストラクタ関数を呼出す前に、そのプロパティを内部呼出しの値に設定すればよいでしょう。

スクリプト001■Singletonパターンを実装したクラス

package {
  import flash.errors.IllegalOperationError;
  public class Singleton {
    private static var instance:Singleton = null;   // インスタンスを格納する
    private static var internallyCalled:Boolean = false;   // 内部呼出しかどうかを示すフラグ
    // コンストラクタ関数
    public function Singleton() {
      if (internallyCalled) {   // フラグが内部呼出しを示せば
        // 本来の処理を行う
        trace("constructor is called");   // テスト用
        internallyCalled = false;   // 内部呼出しのフラグを初期値に戻す
      } else {   // フラグが内部呼出しを示さなければ
        // エラーをthrow
        throw new IllegalOperationError ("Use Singleton.getInstance() to get the instance");
      }
    }
    // Singletonクラスのインスタンスを返す
    public static function getInstance():Singleton {
      if(Singleton.instance == null) {   // インスタンスが未生成なら
        trace("instance is being created");   // テスト用
        internallyCalled = true;   // 内部呼出しのフラグを設定
        instance = new Singleton();   // コンストラクタ関数を呼出す
      }
      return instance;   // 格納されたインスタンスを返す
    }
  }
}

上記スクリプト001のSingletonクラスは、以下のようなフレームアクション(スクリプト002)で簡単にテストすることができます。実行すると、[Output]パネルにはつぎのような出力が表示されます。

instance is being created
constructor is called
true

最初のステートメントでは、コンストラクタ関数の呼出しが行われ、コンストラクタは正常にインスタンスを生成して返します。2行目のステートメントは、新規のインスタンスは生成せず、すでに1行目で生成されたインスタンスを返します。したがって、4行目でふたつのインスタンスは同一であることが示されます。

コメントアウトされた3行目を有効にすると、コンストラクタを外部から呼出すため、コンパイルエラーを発生します。

スクリプト002■予め設定した変数と未定義変数にwithステートメントで値を設定

var mySingleton0:Singleton = Singleton.getInstance();
var mySingleton1:Singleton = Singleton.getInstance();
// var mySingleton2:Singleton = new Singleton();   // コンパイルエラー
trace(mySingleton0 == mySingleton1);

privateなコンストラクタの実装は、ほかにも考えられるでしょう。たとえば、前出注[*2]akihiro kamijo「コンストラクタ(とSingleton)」では、privateなクラスをコンストラクタの引数に指定することで、外部から呼出しができないようにしています。

[*3] デザインパターンは、Javaなどの言語で解説されています。Singletonパターンについては、たとえばTECHSCORE「Singletonパターン」が参考になるでしょう。

[*4] もっとも、SharedObjectクラスは、コンストラクタ関数が呼出せるようです(ドキュメントにはその記載もないので、サポート外とは思われます)。また、SharedObject.getLocal()メソッドに渡す引数が異なると、新たなインスタンスを作成するという仕様になっています。

[*5] Javaも、コンストラクタにprivate修飾子を指定して、Singletonパターンを実装しています(前出注[*3]参照)。


作成者: 野中文雄
作成日: 2006年9月30日


Copyright © 2001-2006 Fumio Nonaka.  All rights reserved.