Vectorのコンストラクタトラップ
Flash Player 10対応のAS3でお試しコードをいろいろ書いているのですが、Vectorクラスでちょっとハマったのでメモしておきます。
Vectorクラスのコンストラクタ
基本からおさらいしておきます。Vectorクラスのコンストラクタは、次のように定義されています。
Vector(length:uint = 0, fixed:Boolean = false)
要素数と、固定長にするかどうか、ということが決められます。
つまり、次のような感じで使うことが想定されており、また、以下のコードは問題なく実行可能です。
var vtest:Vector.<int> = new Vector.<int>(); vtest.push( 1, 2, 3 ); // 内容を追加. trace("> "+vtest); // [trace] > 1,2,3 trace("> "+vtest[0]); // [trace] > 1 var vtest2:Vector.<int> = new Vector.<int>(4); trace("> "+vtest2); // [trace] > 0,0,0,0 trace("> "+vtest2[0]); // [trace] > 0
定数として使いたくてハマった
書きたかったコードは、Vector変数の定義時に内容も決めておく、というものです。
ちなみに以前からある配列クラスのArrayクラスならば以下のコードのように内容を決定できます。
var array:Array = new Array( 5, 6, 7 ); trace("> "+array); // [trace] > 5,6,7 trace("> "+array[0]); // [trace] > 5
これと同様なことをVectorでやりたい、と思って書いた次のコードは二つともエラーになるのです。
// 注:思い通りに動作しないコードです. var vtestE1:Vector.<int> = new Vector.<int>( 5, 6, 7 ); var vtestE2:Vector.<int> = new Vector.<int>( [5, 6, 7] );
私が書いていたコードは二つ目の方で、このコードはコンストラクト時にはエラーにならず、変数読み出し時に内容がない(RangeError)と言われて、訳が分らなくなりハマった次第です。
まぁ、最初に書いたコンストラクタの形を見れば、これらがエラーになるのは一目瞭然なのですが。
冷静に考えると、このコンストラクタのコードでは引数に配列を渡すことが出来ず、Vectorクラスの定数を定義できないことになる。
解決策はトップレベル関数!
と、困りながらいろいろなコードを見ていて以下のようなコードを発見したのです。
var vtest3:Vector.<int> = Vector.<int>([5,6,7]);
一見前述したエラーを出すコードと似ていますが、よく見ると new が無いことに気づきます。
このコードの Vector はトップレベル関数なのです。
引数にはArrayオブジェクトを与える必要があるので、上記のようなコードになるのです。
また、各種コードは以下のようにOKだったり、NGだったりしますが、これらも引数の定義、クラスの定義などを丁寧に見ていくと理解できます。
// OK. const vtest4:Vector.<int> = Vector.<int>( new Array(8,9,10) ); // NG const vtest4:Vector.<int> = Vector.<int>( 11 );
でも、まぁ、ちょっと分りにくい仕組みだよな−、と思わざるを得ない。
解決案としては、「Vectorクラスのコンストラクタに3つ目の引数をArray型で追加して、それを初期値に出来る」という実装が思い浮かぶが、これでは何か不便なことになるのだろうか。