問題
withステートメントを用いると、識別子に参照がないとき、指定したオブジェクト内をまず探して、値を得ようとします。ところが、クラスのメソッド内でwithステートメントを使うと、指定したインスタンスでなく、同名のローカル変数(Activationオブジェクト)やインスタンスメンバー(プロパティやメソッド)の値を取得してしまうことがあります。
たとえば、以下のクラスTest(スクリプト001)は、withステートメントでローカル変数(_array)に設定した配列を指定しているにも拘らず、参照なしにプロパティ(length)やメソッド(push())にアクセスすると、同名のインスタンスプロパティやインスタンスメソッドの値が得られてしまいます(図001)。Testクラスを試すには、クラス定義ファイルTest.asと同階層に保存したFlashムービー(FLA)ファイルのフレームアクションから、つぎのようにコンストラクタを呼出します。
// Flashムービー(FLA)ファィル: Test.asと同階層に保存
// タイムライン: メイン
// フレームアクション
var obj:Test = new Test();
スクリプト001■withで指定したインスタンスよりクラスのインスタンスが先に参照される
// ActionScript 3.0クラス定義ファイル: Test.as
package {
public class Test {
private var length:int = 100;
public function Test() {
// var length:int = 10;
var _array:Array = new Array();
trace(_array.length); // 出力: 0
with (_array) {
trace(length); // 出力: 100
trace(push(0)); // 出力: 1000
}
}
private function push(n:int):int {
return 1000;
}
}
}
|
図001■withで指定した配列でなくインスタンスメンバーの値が[出力]される
なお、上記スクリプト001のコメントアウトされているローカル変数設定のステートメントを有効にすると、インスタンスプロパティでなくこの変数値が先に参照されます。
原因
クラスのメソッド内で使われたwithステートメントは、指定したインスタンスより先にActivationオブジェクトとクラスインスタンス内の識別子を探しにいってしまうようです。ただし、インスタンスメンバーをpublic属性で指定すると、検索の対象からは外れます。ActionScript 3.0のバグだと考えられます[*1]。
[*1] ActionScript 2.0では、このような現象は発生しません(図002)。
図002■ActionScript 2.0ではwithで指定した配列が正しく参照される
|
対処法
withステートメントは使わないことをお勧めします[*2]。
作成者: 野中文雄
作成日: 2008年4月27日