Array associativi

Flash Player 9 e versioni successive, Adobe AIR 1.0 e versioni successive

Un array associativo, talvolta detto anche hash o mappa, utilizza chiavi invece che indici numerici per organizzare i valori memorizzati. Ogni chiave di un array associativo è una stringa univoca che consente di accedere a un valore memorizzato. Gli array associativi sono istanze della classe Object; di conseguenza, ogni chiave corrisponde a un nome di proprietà. Gli array associativi sono insiemi di coppie chiave/valore non ordinati. Le chiavi di un array associativo non sono mai in un ordine specifico.

ActionScript 3.0 utilizza anche un tipo di array associativo avanzato denominato dizionario. I dizionari sono istanze della classe Dictionary all'interno del pacchetto flash.utils e utilizzano chiavi costituite da qualsiasi tipo di dati. In altre parole, le chiavi dei dizionari non sono limitate a valori di tipo String.

Array associativi con chiavi stringa

Esistono due modi per creare degli array associativi in ActionScript 3.0. Il primo modo consiste nell'utilizzare un'istanza Object. Utilizzando un'istanza Object, è possibile inizializzare l'array con un valore letterale. Un'istanza della classe Object, detta anche oggetto generico, è identica dal punto di vista funzionale a un array associativo. Ogni nome di proprietà dell'oggetto generico funge da chiave che fornisce accesso a un valore memorizzato.

Nell'esempio seguente viene creato un array associativo denominato monitorInfo e viene utilizzato un valore letterale oggetto per inizializzare l'array con due coppie chiave/valore:

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

Se non avete l'esigenza di inizializzare l'array quando viene dichiarato, potete utilizzare la funzione di costruzione Object per creare l'array, come indicato di seguito:

var monitorInfo:Object = new Object();

Al termine della creazione dell'oggetto tramite il valore letterale oggetto o la funzione di costruzione della classe Object, è possibile aggiungere nuovi valori all'array mediante l'operatore parentesi ([]) o l'operatore punto (.). Nell'esempio seguente vengono aggiunti due nuovi valori a monitorArray:

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

Notate come la chiave denominata aspect ratio contenga un carattere spazio. Questa operazione è possibile con l'operatore di accesso all'array ([]), ma genera un errore se si tenta di effettuarla con l'operatore punto. L'uso di spazi nei nomi delle chiavi è sconsigliato.

In alternativa, per creare un array associativo potete utilizzare la funzione di costruzione Array (o la funzione di costruzione di qualsiasi classe dinamica) e utilizzare, quindi, l'operatore di accesso all'array ([]) o l'operatore punto (.) per aggiungere coppie chiave/valore all'array. Se dichiarate un array associativo di tipo Array, non potete utilizzare un valore letterale oggetto per inizializzare l'array. Nell'esempio seguente viene creato un array associativo denominato monitorInfo utilizzando la funzione di costruzione Array e viene aggiunta una chiave denominata type e una denominata resolution con i relativi valori.

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

L'uso della funzione di costruzione Array per creare un array associativo non presenta vantaggi. Non potete usare la proprietà Array.length né alcuno dei metodi della classe Array con gli array associativi, anche se utilizzate la funzione di costruzione di Array o il tipo di dati di Array. È preferibile destinare la funzione di costruzione della classe Array alla creazione di array indicizzati.

Array associativi con chiavi oggetto (dizionari)

Con la classe Dictionary è possibile creare array associativi che usano oggetti anziché stringhe come chiavi. Tali array vengono anche chiamati dizionari, hash o mappe. Considerate, ad esempio, un'applicazione che consente di determinare la posizione di un oggetto Sprite in base alla sua associazione a un contenitore specifico. È possibile utilizzare un oggetto Dictionary per mappare ogni oggetto Sprite a un contenitore.

Nel codice seguente vengono create tre istanze della classe Sprite che servono da chiave per l'oggetto Dictionary. A ogni chiave viene assegnato un valore GroupA o GroupB. Tali valori possono essere dati di qualsiasi tipo, tuttavia, nell'esempio, sia GroupA che GroupB sono istanze della classe Object. Di conseguenza, potete accedere al valore associato a ciascuna chiave per mezzo dell'operatore di accesso all'array ([]), come mostrato nel seguente codice:

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");  
}

Iterazioni con chiavi oggetto

Potete eseguire iterazioni all'interno del contenuto di un oggetto Dictionary mediante la funzione ciclica for..in o for each..in. Il ciclo for..in consente di eseguire iterazioni in base a chiavi, mentre il ciclo for each..in consente di eseguire iterazioni in base ai valori associati a ogni chiave.

Il ciclo for..in può essere utilizzato per accedere direttamente alle chiavi oggetto di un oggetto Dictionary. Potete inoltre accedere ai valori dell'oggetto Dictionary per mezzo dell'operatore di accesso all'array ([]). Nel codice seguente viene utilizzato l'esempio precedente del dizionario groupMap per illustrare come eseguire un'iterazione in un oggetto Dictionary con il ciclo for..in:

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

Il ciclo for each.. può essere utilizzato per accedere direttamente ai valori di un oggetto Dictionary. Anche nel codice seguente viene utilizzato il dizionario groupMap per illustrare come eseguire un'iterazione in un oggetto Dictionary con il ciclo for each..in:

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

Chiavi oggetto e gestione della memoria

In Adobe® Flash® Player e Adobe® AIR™ viene utilizzato un sistema di garbage collection che consente di ripristinare memoria non più utilizzata. Se un oggetto non presenta riferimenti associati, diventa idoneo per il processo di garbage collection e la memoria liberata viene ripristinata alla successiva esecuzione del sistema di garbage collection. Il codice seguente consente, ad esempio, di creare un nuovo oggetto e di assegnare un riferimento a tale oggetto mediante la variabile myObject:

var myObject:Object = new Object();

Fintanto che esiste un riferimento all'oggetto, il sistema di garbage collection non ripristinerà la memoria occupata dall'oggetto. Se il valore di myObject viene modificato in modo da puntare a un oggetto differente o viene impostato sul valore null, la memoria occupata dall'oggetto originale diventa disponibile per la garbage collection, ma solo se non vi sono altri riferimenti che puntano all'oggetto originale.

Se usate myObject come chiave in un oggetto Dictionary, si crea un altro riferimento all'oggetto originale. Il codice seguente consente, ad esempio, di creare due riferimenti a un oggetto, la variabile myObject e la chiave nell'oggetto myMap:

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

Per fare in modo che l'oggetto a cui fa riferimento myObject diventi disponibile per la garbage collection, dovete rimuovere tutti i riferimenti. In questo caso, modificate il valore di myObject ed eliminate la chiave myObject da myMap, come illustrato nel codice seguente:

myObject = null; 
delete myMap[myObject];

In alternativa, potete utilizzare il parametro useWeakReference della funzione di costruzione Dictionary per rendere tutte le chiavi del dizionario riferimenti deboli. Il sistema di garbage collection ignora i riferimenti deboli, vale a dire che un oggetto che presenta solo riferimenti deboli è disponibile per l'operazione di garbage collection. Nel codice seguente, ad esempio, non è necessario eliminare la chiave myObject da myMap per rendere l'oggetto disponibile per la garbage collection:

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.