結合配列

Flash Player 9 以降、Adobe AIR 1.0 以降

ハッシュまたはマップとも呼ばれる結合配列は、格納される値を構成するために、数値インデックスの代わりにキーを使用します。結合配列に使用する個々のキーは、それぞれに対応する特定の格納値にアクセスするための一意のストリングです。 結合配列は Object クラスのインスタンスであり、したがって、各キーはそれぞれ 1 つのプロパティ名に対応します。 結合配列は、キー / 値ペアの集合からなる、ソートされていないコレクションです。 結合配列内のキーに何らかの決まった順序があるかのような前提でコードを記述してはなりません。

また、ActionScript 3.0 では、新たにディクショナリと呼ばれる高機能な結合配列を使用できるようになりました。ディクショナリは、flash.utils パッケージの Dictionary クラスのインスタンスですが、任意のデータ型にできるキーを使用します。つまり、ディクショナリのキーは String 型の値である必要はありません。

ストリングキーを使用した結合配列

ActionScript 3.0 では、2 つの方法で結合配列を作成します。最初の方法は、Object インスタンスを使用する方法です。Object インスタンスを使用することにより、オブジェクトリテラルで配列を初期化できます。Object クラスのインスタンスは汎用オブジェクトとも呼ばれますが、機能的には結合配列と同じです。汎用オブジェクトの個々のプロパティ名が、格納した個々の値にアクセスするためのキーとして機能します。

次の例では、monitorInfo という名前の結合配列を作成します。オブジェクトリテラルを使用して、2 つのキーと値のペアが指定された配列を初期化します。

var monitorInfo:Object = {type:"Flat Panel", resolution:"1600 x 1200"}; 
trace(monitorInfo["type"], monitorInfo["resolution"]);  
// output: Flat Panel 1600 x 1200

宣言時に配列を初期化する必要がある場合は、次のように、Object コンストラクターを使って配列を作成できます。

var monitorInfo:Object = new Object();

オブジェクトリテラルまたは Object クラスのコンストラクターで配列を作成した後は、配列アクセス([])演算子またはドット演算子()を使用して新しい値を追加できます。)を使用して新しい値を追加できます。次の例では、monitorArray に新しい値を 2 つ追加します。

monitorInfo["aspect ratio"] = "16:10"; // bad form, do not use spaces 
monitorInfo.colors = "16.7 million"; 
trace(monitorInfo["aspect ratio"], monitorInfo.colors); 
// output: 16:10 16.7 million

この例で、aspect ratio というキーの名前には空白文字が含まれています。配列アクセス([])演算子ではこのような名前も使用できますが、ドット演算子で使用するとエラーになります。空白文字を含んだキー名を使用することはお勧めしません。

結合配列を作成する 2 つ目の方法は、Array コンストラクター(またはダイナミッククラスのコンストラクター)を使用し、配列アクセス([])演算子またはドット演算子(.)を使用して、キーと値のペアを配列に追加します。結合配列を Array 型として宣言した場合、オブジェクトリテラルで配列を初期化することはできません。 次の例では、monitorInfo という名前の結合配列を Array コンストラクターで作成し、type および resolution という 2 つのキーとそれぞれに対応する値を追加します。

var monitorInfo:Array = new Array(); 
monitorInfo["type"] = "Flat Panel"; 
monitorInfo["resolution"] = "1600 x 1200"; 
trace(monitorInfo["type"], monitorInfo["resolution"]);  
// output: Flat Panel 1600 x 1200

結合配列の作成に Array コンストラクターを使用するメリットはありません。 たとえ Array コンストラクターや Array データ型を使用して宣言した結合配列であっても、Array.length プロパティや Array クラスのメソッドはまったく使用できないからです。Array コンストラクターはインデックス配列を作成する場合に限って使用するようお勧めします。

オブジェクトのキーを使用した結合配列 (ディクショナリ)

Dictionary クラスを使用すると、ストリングではなくオブジェクトをキーとする結合配列を作成できます。 そのような配列は、ディクショナリ、ハッシュ、またはマップと呼ばれることがあります。 例えば、特定のコンテナとの位置関係によって Sprite オブジェクトの位置が決まるようなアプリケーションでは、 個々の Sprite オブジェクトをコンテナへマップする場合に Dictionary オブジェクトを使用できます。

次のコードでは、Dictionary オブジェクトのキーとして使用する Sprite クラスのインスタンスを 3 つ作成します。 各キーに対しては、GroupA または GroupB いずれかの値を格納します。格納する値には任意のデータ型を使用できますが、この例では GroupAGroupB のいずれも Object クラスのインスタンスです。次に、配列アクセス演算子([])を使用して、各キーに対応する値にアクセスします。

import flash.display.Sprite; 
import flash.utils.Dictionary; 
 
var groupMap:Dictionary = new Dictionary(); 
 
// objects to use as keys 
var spr1:Sprite = new Sprite(); 
var spr2:Sprite = new Sprite(); 
var spr3:Sprite = new Sprite(); 
 
// objects to use as values 
var groupA:Object = new Object(); 
var groupB:Object = new Object(); 
 
// Create new key-value pairs in dictionary. 
groupMap[spr1] = groupA; 
groupMap[spr2] = groupB; 
groupMap[spr3] = groupB; 
 
if (groupMap[spr1] == groupA) 
{ 
    trace("spr1 is in groupA");  
} 
if (groupMap[spr2] == groupB) 
{ 
    trace("spr2 is in groupB");  
} 
if (groupMap[spr3] == groupB) 
{ 
    trace("spr3 is in groupB");  
}

オブジェクトのキーを使用した反復処理

for..in ループまたは for each..in ループで Dictionary オブジェクトの内容の繰り返し処理を実行することができます。 for..in ループを使用すると、キーに基づいて反復処理することができます。一方、for each..in ループを使用すると、各キーに関連付けられた値に基づいて反復処理することができます。

for..in ループの場合、Dictionary オブジェクト内のオブジェクトキーに直接アクセスできます。また、配列アクセス演算子([])を使用すれば Dictionary オブジェクト内の値にアクセスできます。次のコードでは、前の例と同じ groupMap ディクショナリを使用して、for..in ループで Dictionary オブジェクトの内容を反復処理する方法を示します。

for (var key:Object in groupMap) 
{ 
    trace(key, groupMap[key]); 
} 
/* output: 
[object Sprite] [object Object] 
[object Sprite] [object Object] 
[object Sprite] [object Object] 
*/

for each..in ループの場合、Dictionary オブジェクトの値に直接アクセスできます。次のコードでもやはり groupMap ディクショナリを使用して、for each..in ループで Dictionary オブジェクトの内容を反復処理する方法を示します。

for each (var item:Object in groupMap) 
{ 
    trace(item); 
} 
/* output: 
[object Object] 
[object Object] 
[object Object] 
*/

オブジェクトキーとメモリ管理

Adobe® Flash® Player と Adobe® AIR™ では、使用されなくなったメモリはガベージコレクションのシステムによって開放されます。オブジェクトはどこからも参照されなくなった時点でガベージコレクションの対象とされ、次回ガベージコレクションが実行されるとき、そのオブジェクトに使用されていたメモリが解放されます。 例えば次のコードでは、新しいオブジェクトを作成し、そのオブジェクトへの参照を myObject という変数に割り当てています。

var myObject:Object = new Object();

オブジェクトに対して何らかの参照が存在する間は、そのオブジェクトが使用しているメモリがガベージコレクションのシステムによって解放されることはありません。 myObject の値が別のオブジェクトを参照するように変更されるか、または null に設定されると、それまで参照先となっていたオブジェクトはガベージコレクションの対象とされます(そのオブジェクトに対する参照が他に存在しない場合)。

この myObject を Dictionary オブジェクトのキーとして使用すると、参照先オブジェクトに対する参照がもう 1 つ作成されます。例えば次のコードでは、1 つのオブジェクトに対して 2 つの参照、つまり myObject 変数と、myMap オブジェクトのキーを作成しています。

import flash.utils.Dictionary; 
 
var myObject:Object = new Object(); 
var myMap:Dictionary = new Dictionary(); 
myMap[myObject] = "foo";

myObject で参照しているオブジェクトをガベージコレクションに対して有効にするには、そのオブジェクトに対する参照をすべて削除する必要があります。この場合、そのためには myObject の値を変更するのに加え、myMap から myObject のキーを削除します。

myObject = null; 
delete myMap[myObject];

別の方法として、Dictionary コンストラクターに対して useWeakReference パラメーターを指定し、すべてのディクショナリキーを弱参照にすることもできます。弱参照はガベージコレクションのシステムで無視されるため、弱参照による参照しか受けていないオブジェクトはガベージコレクションの対象となります。 例えば次のコードでは、myMap 内の myObject キーを削除しなくても、該当するオブジェクトをガベージコレクションの対象とすることができます。

import flash.utils.Dictionary; 
 
var myObject:Object = new Object(); 
var myMap:Dictionary = new Dictionary(true); 
myMap[myObject] = "foo"; 
myObject = null; // Make object eligible for garbage collection.