ActionScript3.0のDictionaryクラス

今回は、ActionScript3.0のDictionaryクラスに関する学習メモです。ActionScript3.0で結合配列(連想配列)を使う際、多くの場合Objectクラスを使用しますが、Dictionaryクラスを使用すると配列のキーにオブジェクトの参照を指定することができます。

まず、簡単な例から試してみます。Dictionaryクラスのインスタンスは、new演算子で生成します。配列のキーは、オブジェクトの参照だけでなく、文字列やインデックス(添え字)でも指定できることが確認できます。

ActionScript3.0

var _sp:Sprite = new Sprite();
var _dic:Dictionary = new Dictionary();
_dic[0] = new Sprite();
_dic["foo"] = "abcde";
_dic.bar = 1000;
_dic[_sp] = true;
trace(_dic[0]);
trace(_dic.foo);
trace(_dic["bar"]);
trace(_dic[_sp]);

一応、Object型でも配列のキーに参照を使って試してみました。下記のコードはコンパイルは通りますが、期待した値を得ることができません。Object型では、キーに参照を使った場合、インスタンスの文字列表現、つまりtoString()の戻り値がキーとなっていることが確認できます。

ActionScript3.0

var sp1:Sprite = new Sprite();
var sp2:Sprite = new Sprite();
var _obj:Object = {};
_obj[sp1] = "SP1";
_obj[sp2] = "SP2";
trace(_obj[sp1]);
trace(_obj[sp2]);
trace(_obj[sp1.toString()]);
trace(_obj["[object Sprite]"]);

次は、Dictionaryインスタンスに格納した値を削除してみます。nullを代入した場合には値のみが削除され、delete演算子を使用した場合はキーも削除されundefinedが出力されることが確認できます。

ActionScript3.0

var sp1:Sprite = new Sprite();
var sp2:Sprite = new Sprite();
var _dic:Dictionary = new Dictionary();
_dic[sp1] = "hoge";
_dic[sp2] = "piyo";
_dic[sp1] = null;
delete _dic[sp2];
trace(_dic[sp1]);
trace(_dic[sp2]);

またDictionaryクラスは、コンストラクタの第1引数でtrueを指定するとキーの参照に弱参照を使用することができます。つまり弱参照を使用した場合、キーに使ったインスタンスがDictionary以外、どこからも参照されていない場合、そのインスタンスはガーベジコレクションの対象になります。キーに使ったインスタンスがガーベジコレクションで削除されるとキーに対応する値も削除されます。

下記の例では、enterFrameでDictionaryインスタンスの要素数をtrace()しています。stageをクリックすると1000個のSpriteをそれぞれキーとしてDictionaryに要素を追加していますが、ガーベジコレクションのタイミングでDictionaryインスタンスの要素数が減ることが確認できます。

ActionScript3.0

var _dic:Dictionary = new Dictionary(true);
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
stage.addEventListener(MouseEvent.CLICK, clickHandler);
function enterFrameHandler(e:Event):void {
  var i:Number = 0;
  for each (var str in _dic) {
    i++;
  }
  trace(i);
}
function clickHandler(e:MouseEvent):void {
  var sp:Sprite;
  for (var i:int = 0; i < 1000; i++) {
    sp = new Sprite();
    _dic[sp] = sp.name;
  }
}

Dictionaryクラスは、ArrayやVectorと比べると処理速度は遅いようですが、使いどころがたくさんあると感じました。例えば、ボタンのリンク先のURLを格納したり、インスタンスのプロパティを動的に格納することはもちろん、何よりオブジェクト同士を関連付けることができるので、アイデア次第ではかなり面白いことができそうです。色々と試していきたいと思います。