« Pictori | Main | The Seattle Public Library »

ActionScriptの仕様?

年末に、thaのグリーティングカードのAmazonAPIの部分を実装していた時に一箇所はまったところがあった。その謎が今解き明かされたので思い出残し(謎)に書いてみる。ActionScriptでクラスを作ってた時の話。

あるクラスのbooksフィールド(Array)にAmazonAPIで検索した結果を入れる事にした。このクラスは、検索一回する毎に1インスタンス生成される。つまり、「HAPPY」と「NEW」を検索した場合、HappyインスタンスとNewインスタンスができる。

で、実際にそれを動かして見ると、なぜか、Happyインスタンスの結果とNewインスタンスのbooksフィールドが混ざっている。コードを見直したけど、そんな問題が起きるような箇所はない。そもそもインスタンスが違うフィールドが混ざるわけが無い。無論、静的変数ではない。同じタイミング(Flashでこれをマルチスレッドと呼ぶかどうか知らないけど、そういう事)でLoadVarsを使うとFlash内部で結果が混ざっておかしくなるのかなとかも考えたんだけど、デバッグした結果、LoadVarsの動作は正常だった。

3時間ぐらい試行錯誤結果、ある事に気づく。Happyインスタンス、Newインスタンスのクラスは、それまで、フィールド宣言の箇所でbooksフィールドをnew Array()して初期化してたのを、インスタンスを作った後にbooksフィールドをnew Array()するようにしたら治った。この動作マジで謎だーと思ったんだけど、動作が正常なのでこれ以上詮索するのはやめた。

で、今日もFlashやりつつActionScriptのヘルプ眺めてたら、こんなの発見。以下引用。

配列をインラインで初期化した場合、クラスのすべてのインスタンスに対し配列が 1 つだけ作成されます。

class Bar {
var foo:Array = new Array();
}

なんつー仕様だ、これ。これって、ActionScriptじゃなくてECMAScriptの仕様なのかな。とにかく、混乱するって。だってこれ、要は、フィールド宣言で配列を初期化した場合、静的変数になってしまうって事とあまり変わらないって事でしょ。

なんだかなー。

ていうか、これ既知?

因みにどういう事かと言うとこういうことです。

TestArrayクラス。

class ArrayTest { public var arr:Array = new Array(); }

flaの1フレーム目。

var a:ArrayTest = new ArrayTest(); var b:ArrayTest = new ArrayTest(); a.arr.push("hello"); b.arr.push("world"); for (var i = 0; i < a.arr.length; i++) { trace(a.arr[i]); }

ビックリすることに結果は、

hello
world

です。因みに普通に考えて期待される結果は、helloだけ。

Post a comment