ようやく new Dictionary() が実行できるようになったので続きです。
weak-value ディクショナリー
以前の記事に書いたように、Dictionary クラスは weak-key ディクショナリーの機能を持っています。キーオブジェクトへの参照が弱い参照のため、使われなくなったキーとそのエントリーを自動的に開放するという使い方ができます。
一方、値として管理されているオブジェクトがしばらく参照されなかったら自動的に開放するという使い方はできません。
このようなケースは(本来であれば) weak-value ディクショナリーを使う場面です。weak-value ディクショナリーでは値オブジェクトへの参照が弱い参照のため、他から参照されていない値オブジェクトはガーベッジコレクションの対象になります。
さて、現状で weak-value ディクショナリーを実現するには Dictionary のキーと値の扱いを入れ替えてしまうのが簡単そうです。Proxy を使うと以下の用に実現できます。
public dynamic class MyDictionary extends Proxy { private var _dict:Object; public function MyDictionary() { _dict = new Dictionary(true); } override flash_proxy function setProperty(name:*, value:*):void { // 値とキーを逆にしてエントリーを追加 _dict[value] = name; } }
本来キーとして使われるオブジェクトを値として格納したので、取り出す際には一つ一つ調べることになります。
override flash_proxy function getProperty(name:*):* { for (var value:* in _dict) { if (_dict[value] == name) { return value; } } }
ただこの方法ではエントリーが多くなるに連れ参照時のパフォーマンスが悪くなりそうです。
そこで、ちょっと贅沢ですがエントリーごとに Dictionary を生成するようにしてみます。
override flash_proxy function setProperty(name:*, value:*):void { // エントリ専用の Dictionary オブジェクト生成 var dict4Val:Dictionary = new Dictionary(true); // 値とキーを逆にしてエントリーを追加 dict4Val[value] = name; // Dictionary オブジェクトを値として設定 _dict[name] = dict4Val; }
今回は Dictionary が一つしかエントリを持たないため、取り出す際は最初に見つかったものをそのまま返すことができます。
override flash_proxy function getProperty(name:*):* { // まず対応する Dictionary オブジェクトを取り出す var dict4Val:Dictionary = _dict[name]; // dict4Val は一つしかキーを持たないはず for (var value:* in dict4Val) { // 見つかった値を返す return value; } }