Tableaux associatifs

Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures

Un tableau associatif, parfois appelé hachage ou mappage, utilise des clés plutôt qu’un index numérique pour organiser des valeurs stockées. Chaque clé dans un tableau associatif est une chaîne unique qui est utilisée pour accéder à une valeur stockée. Un tableau associatif est une occurrence de la classe Object, ce qui signifie que chaque clé correspond à un nom de propriété. Les tableaux associatifs sont des collections non triées de paires de clés et de valeurs. Votre code ne doit pas s’attendre à ce que les clés d’un tel tableau se présentent dans un ordre précis.

ActionScript 3.0 contient aussi un type avancé de tableau associatif appelé dictionnaire. Les dictionnaires, qui sont des occurrences de la classe Dictionary dans le package flash.utils, utilisent des clés de tout type de données. En d’autres termes, les clés de dictionnaire ne sont pas limitées à des valeurs de type String.

Tableaux associatifs avec clés de chaîne

Deux méthodes permettent de créer des tableaux associatifs dans ActionScript 3.0. La première consiste à utiliser une occurrence de Object. Celle-ci vous permet d’initialiser votre tableau avec un littéral d’objet. Une occurrence de la classe Object, également appelée objet générique, fonctionne comme un tableau associatif. Chaque nom de propriété de l’objet générique devient la clé qui permet d’accéder à une valeur stockée.

L’exemple suivant crée un tableau associatif appelé monitorInfo, à l’aide d’un littéral d’objet pour initialiser le tableau avec deux paires de clés et de valeurs :

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

Si vous n’avez pas besoin d’initialiser le tableau lors de la déclaration, vous pouvez utiliser le constructeur Object pour créer le tableau, comme suit :

var monitorInfo:Object = new Object();

Une fois que le tableau est créé à l’aide d’un littéral d’objet ou du constructeur de la classe Object, vous pouvez lui ajouter de nouvelles valeurs à l’aide de l’opérateur ([]) d’accès au tableau ou de l’opérateur point (.). L’exemple suivant ajoute deux nouvelles valeurs à 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

La clé appelée aspect ratio contient un caractère d’espace. Cela est possible dans le cas de l’opérateur ([]) d’accès au tableau, mais avec l’opérateur point, une erreur se produit. L’utilisation d’espace dans le nom de vos clés n’est donc pas conseillée.

La seconde méthode pour créer un tableau associatif consiste à utiliser le constructeur Array (ou le constructeur d’une classe dynamique), puis à utiliser l’opérateur ([]) d’accès au tableau ou l’opérateur point (.) pour ajouter les paires de clés et de valeurs au tableau. Si vous déclarez votre tableau associatif comme étant de type Array, vous ne pouvez pas utiliser de littéral d’objet pour l’initialiser. Ce code crée un tableau associatif appelé monitorInfo à l’aide du constructeur Array, et ajoute les clés appelées type et resolution, ainsi que leurs valeurs :

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’utilisation du constructeur Array pour créer un tableau associatif ne présente aucun avantage. Vous ne pouvez pas utiliser la propriété Array.length ou une méthode de la classe Array avec des tableaux associatifs, même si vous utilisez le constructeur Array ou le type de données Array. Il est préférable d’utiliser le constructeur Array pour créer des tableaux indexés.

Tableaux associatifs avec clés d’objet (dictionnaires)

Vous pouvez utiliser la classe Dictionary pour créer un tableau associatif qui utilise des objets pour les clés au lieu de chaînes. Ces tableaux sont parfois appelés dictionnaires, hachages ou mappages. Par exemple, supposez que vous avez une application qui détermine l’emplacement d’un objet Sprite selon son association avec un conteneur spécifique. Vous pouvez utiliser un objet Dictionary pour mapper chaque objet Sprite à un conteneur.

Le code suivant crée trois occurrences de la classe Sprite qui servent de clés pour l’objet Dictionary. La valeur GroupA ou GroupB est affectée à chaque clé. Les valeurs peuvent être de n’importe quel type de données, mais dans cet exemple, GroupA et GroupB sont des occurrences de la classe Object. Vous pouvez ensuite accéder à la valeur associée à chaque clé avec l’opérateur d’accès au tableau ([]), comme illustré dans le code suivant :

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

Itération avec des clés d’objet

Vous pouvez parcourir en boucle le contenu d’un objet Dictionary à l’aide d’une boucle for..in ou d’une boucle for each..in. Une boucle for..in vous permet d’effectuer une itération en fonction des clés, tandis qu’une boucle for each..in vous permet d’effectuer une itération en fonction des valeurs associées à chaque clé.

Utilisez la boucle for..in pour accéder directement aux clés d’objet d’un objet Dictionary. Vous pouvez également accéder aux valeurs de l’objet Dictionary avec l’opérateur d’accès au tableau ([]). Le code suivant utilise l’exemple précédent du dictionnaire groupMap pour indiquer comment parcourir en boucle un objet Dictionary avec la boucle 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] 
*/

Utilisez la boucle for each..in pour accéder directement aux valeurs d’un objet Dictionary. Le code suivant utilise également le dictionnaire groupMap pour indiquer comment parcourir en boucle un objet Dictionary avec la boucle for each..in :

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

Clés d’objet et gestion de la mémoire

Adobe® Flash® Player et Adobe® AIR™ utilisent un système de nettoyage permettant de récupérer la mémoire qui n’est plus utilisée. Lorsque aucune référence ne pointe vers un objet, ce dernier peut être nettoyé et la mémoire récupérée au prochain nettoyage. Par exemple, le code suivant crée un objet et lui affecte une référence à la variable myObject :

var myObject:Object = new Object();

Tant que des références à l’objet existent, le système de nettoyage ne récupère pas la mémoire que l’objet occupe. Si la valeur de myObject est modifiée et qu’elle pointe vers un autre objet ou qu’elle est définie sur null, la mémoire occupée par l’objet d’origine peut être nettoyée. Néanmoins, aucune autre référence à l’objet d’origine ne doit exister.

Si vous utilisez myObject comme clé dans un objet Dictionary, vous créez une autre référence à l’objet d’origine. Par exemple, le code suivant crée deux références à un objet, la variable myObject et la clé dans l’objet myMap :

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

Pour que l’objet référencé par myObject puisse être nettoyé, vous devez supprimer toutes ses références. Dans ce cas, vous devez modifier la valeur de myObject et supprimer la clé myObject de myMap, comme indiqué dans le code suivant :

myObject = null; 
delete myMap[myObject];

Vous pouvez également utiliser le paramètre useWeakReference du constructeur Dictionary pour que toutes les clés de dictionnaire deviennent des références faibles. Le système de nettoyage ignore les références faibles. Par conséquent, un objet n’ayant que des références faibles peut être nettoyé. Par exemple, dans le code suivant, vous n’avez pas besoin de supprimer la clé myObject de myMap pour que l’objet puisse être nettoyé :

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.