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だけ。
Posted by: Anonymous | January 7, 2005 06:39 PM