Matrizes associativas

Flash Player 9 e posterior, Adobe AIR 1.0 e posterior

Uma matriz associativa, às vezes chamadas de hash ou mapa , usa chaves em vez de índices numéricos para organizar os valores armazenados. Cada chave de uma matriz associativa é uma string exclusiva que é usada para acessar um valor armazenado. Uma matriz associativa é uma ocorrência da classe Object, o que indica que cada chave corresponde a um nome de propriedade. As matrizes associativas são coleções não ordenadas de pares de chave e valor. Seu código não deve esperar que as chaves de uma matriz associativa estejam em uma ordem específica.

O ActionScript 3.0 também inclui um tipo avançado de matriz associativa chamado dicionário . Os dicionários, que são ocorrências da classe Dictionary no pacote flash.utils, usa chaves que podem ser de qualquer tipo de dados. Em outras palavras, as chaves de dicionário não estão limitadas aos valores do tipo String.

Matrizes associativas com chaves de string

Há duas maneiras de criar matrizes associativas no ActionScript 3.0. A primeira alternativa é usar uma ocorrência de Object. Ao usar essa ocorrência, será possível inicializar a matriz com um literal de objeto. Uma ocorrência da classe Object, também chamada de objeto genérico , tem a mesma funcionalidade de uma matriz associativa. Cada nome de propriedade do objeto genérico serve como a chave que fornece acesso a um valor armazenado.

O exemplo a seguir cria uma matriz associativa chamada monitorInfo , usando um literal de objeto para inicializar a matriz com dois pares de chave e valor:

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

Se não for necessário inicializar a matriz no tempo da declaração, use o construtor Object para criar a matriz da seguinte maneira:

var monitorInfo:Object = new Object();

Depois que a matriz é criada com um literal de objeto ou um construtor da classe Object, você pode adicionar novos valores à matriz usando o operador de acesso à matriz ( [] ) ou o operador de ponto ( . ). O exemplo a seguir adiciona dois novos valores 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

Observe que a chave chamada aspect ratio contém um caractere de espaço. Isso é possível com o operador de acesso à matriz ( [] ), mas gera um erro se a tentativa for feita com o operador ponto. Não é recomendado usar espaços em nomes de chave.

A segunda maneira de criar uma matriz associativa é usar o construtor Array (ou o construtor de qualquer classe dinâmica) e usar o operador de acesso à matriz ( [] ) ou o operador de ponto ( . ) para adicionar os pares de chave e valor à matriz. Se declarar que a matriz associativa é do tipo Array, você não poderá usar um literal de objeto para inicializar a matriz. O exemplo a seguir cria uma matriz associativa chamada monitorInfo usando o construtor Array e adiciona uma chave chamada type e uma chave chamada resolution , junto com seus valores:

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

Não há nenhuma vantagem em usar o construtor Array para criar uma matriz associativa. Você não pode usar a propriedade Array.length ou algum método da classe Array com matrizes associativas, mesmo se o construtor Array ou o tipo de dados Array for usado. O uso do construtor Array é mais adequado para a criação de matrizes indexadas.

Matrizes associativas com chaves de objeto (Dicionários)

É possível usar a classe Dictionary para criar uma matriz associativa que usa objetos para chaves em vez de strings. Essas matrizes às vezes são chamadas de dicionários, hashes ou mapas. Pense, por exemplo, em um aplicativo que determina o local de um objeto Sprite com base em sua associação com um recipiente específico. Você pode usar um objeto Dictionary para mapear cada objeto Sprite para um recipiente.

O código a seguir cria três ocorrências da classe Sprite que servem como chaves para o objeto Dictionary. Cada chave recebe o valor GroupA ou GroupB . Os valores podem ser de qualquer tipo de dados, mas, nesse exemplo, GroupA e GroupB são ocorrências da classe Object. Posteriormente, você poderá acessar o valor associado a cada chave com o operador de acesso à matriz ( [] ), como mostra o código a seguir:

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

Iteração com chaves de objeto

É possível percorrer o conteúdo de um objeto Dictionary com um loop for..in ou um loop for each..in . O loop for..in permite percorrer o conteúdo com base nas chaves, enquanto o loop for each..in baseia-se nos valores associados a cada chave.

Use o loop for..in para acessar diretamente as chaves de um objeto Dictionary. Você também pode acessar os valores do objeto Dictionary com o operador de acesso à matriz ( [] ). O código a seguir usa o exemplo anterior do dicionário groupMap para mostrar como percorrer um objeto Dictionary com o loop 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] 
*/

Use o loop for each..in para acessar diretamente os valores de um objeto Dictionary. O código a seguir também usa o dicionário groupMap para mostrar como percorrer um objeto Dictionary com o loop for each..in:

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

Gerenciamento de memória e chaves de objeto

O Adobe® Flash® Player e o Adobe® AIR™ usam um sistema de coleta de lixo para recuperar a memória que não é mais usada. Quando um objeto não tem nenhuma referência apontada para ele, está qualificado para a coleta de lixo e a memória é recuperada na próxima vez em que o sistema é executado. Por exemplo, o código a seguir cria um novo objeto e atribui uma referência do objeto à variável myObject :

var myObject:Object = new Object();

Contanto que exista alguma referência ao objeto, o sistema de coleta de lixo não recuperará a memória ocupada pelo objeto. Se o valor de myObject for alterado de modo que aponte para um objeto diferente ou seja definido como o valor null , a memória ocupada pelo objeto original se qualificará para a coleta de lixo, mas somente se não houver nenhuma outra referência ao objeto original.

Se myObject for usado como uma chave em um objeto Dictionary, outra referência ao objeto original estará sendo criado. Por exemplo, o código a seguir cria duas referências a um objeto: a variável myObject e a chave no objeto myMap :

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

Para que o objeto mencionado por myObject se qualifique para a coleta de lixo, remova todas as referências a ele. Nesse caso, altere o valor de myObject e exclua a chave myObject de myMap , como mostra o código a seguir:

myObject = null; 
delete myMap[myObject];

Como alternativa, você pode usar o parâmetro useWeakReference do construtor Dictionary para que todas as chaves de dicionário sejam referências fracas . O sistema de coleta de lixo ignora as referências fracas e, desse modo, um objeto que tem apenas referências fracas se qualifica para a coleta de lixo. Por exemplo, no código a seguir, não é necessário excluir a chave myObject de myMap para que o objeto se qualifique para coleta de lixo:

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.