Tipi di dati

Un tipo di dati definisce un set di valori. Ad esempio, il tipo di dati Boolean comprende esattamente due valori: true e false. Oltre a Boolean, ActionScript 3.0 definisce vari altri tipi di dati di uso comune, come String, Number e Array. È inoltre possibile creare tipi di dati personalizzati utilizzando le classi o le interfacce per definire un set di valori specifici. In ActionScript 3.0 tutti i valori, di base o complessi, sono oggetti.

Un valore di base appartiene a uno dei tipi di dati seguenti: Boolean, int, Number, String e uint. I valori di base solitamente consentono di lavorare con maggiore rapidità rispetto a quando si utilizzano valori complessi, perché ActionScript memorizza i valori di base con un metodo speciale che permette di ottimizzare la memoria e la velocità di elaborazione.

Nota: per i lettori interessati ai dettagli tecnici: ActionScript memorizza i valori di base internamente come oggetti immutabili. Questo tipo di memorizzazione permette di passare un riferimento anziché un valore, ottenendo lo stesso effetto. In questo modo è possibile ridurre l'uso della memoria e aumentare la velocità, dal momento che i riferimenti hanno dimensioni notevolmente inferiori ai valori veri e propri.

Un valore complesso è qualunque valore diverso da un valore di base. I tipi di dati che definiscono set di valori complessi includono Array, Date, Error, Function RegExp, XML e XMLList.

Molti linguaggi di programmazione fanno distinzione tra i valori di base e i relativi oggetti wrapper. Java, ad esempio, prevede un valore di base int e la classe wrapper java.lang.Integer che lo contiene. I valori di base Java non sono oggetti, ma i relativi wrapper lo sono, il che rende i valori di base utili per determinate operazioni e gli oggetti wrapper più indicati per altre. In ActionScript 3.0, i valori di base e i relativi oggetti sono, ai fini pratici, indistinguibili. Tutti i valori, compresi quelli di base, sono oggetti. Il runtime tratta questi tipi di base come casi speciali che si comportano come oggetti ma non richiedono il lavoro di elaborazione solitamente associato alla creazione di oggetti. Ciò significa che le due righe di codice seguenti sono equivalenti:

var someInt:int = 3; 
var someInt:int = new int(3);

Tutti i tipi di dati di base e complessi elencati sopra sono definiti dalle classi di base di ActionScript 3.0. Tali classi consentono di creare oggetti utilizzando valori letterali anziché l'operatore new. Ad esempio, è possibile creare un array specificando un valore letterale oppure la funzione di costruzione della classe Array, come nell'esempio seguente:

var someArray:Array = [1, 2, 3]; // literal value 
var someArray:Array = new Array(1,2,3); // Array constructor

Verifica del tipo

La verifica del tipo può avvenire sia in fase di compilazione che di runtime. I linguaggi che prevedono tipi statici, come C++ e Java, eseguono la verifica del tipo in fase di compilazione, mentre quelli che prevedono tipi dinamici, come Smalltalk e Python, gestiscono la verifica del tipo in fase di runtime. ActionScript 3.0 appartiene alla seconda categoria ed esegue la verifica del tipo in fase di runtime, ma supporta anche la verifica in fase di compilazione tramite una modalità speciale del compilatore definita modalità rigorosa. Nella modalità rigorosa la verifica del tipo avviene sia in fase di compilazione che di runtime, mentre in modalità standard viene eseguita solo in fase di runtime.

I linguaggi con assegnazione dinamica del tipo offrono una grande flessibilità in fase di strutturazione del codice, tuttavia comportano il rischio che gli errori di tipo si manifestino in fase di runtime. Al contrario, i linguaggi con tipi statici segnalano tutti gli errori di tipo in fase di compilazione ma richiedono che le informazioni sui tipi siano già note in tale fase.

Verifica del tipo in fase di compilazione

La verifica del tipo in fase di compilazione è spesso preferita nei progetti di grandi dimensioni perché, con il crescere delle dimensioni del progetto, la flessibilità dei tipi di dati perde generalmente importanza a favore della possibilità di rilevare tutti gli errori di tipo con la massima tempestività. È per questo motivo che, per impostazione predefinita, il compilatore ActionScript in Flash Professional e in Flash Builder è configurato per essere eseguito in modalità rigorosa.

Adobe Flash Builder

Potete disabilitare la modalità rigorosa in Flash Builder tramite le impostazioni del compilatore ActionScript nella finestra di dialogo delle proprietà del progetto.

Per eseguire la verifica del tipo in fase di compilazione, il compilatore deve conoscere il tipo di dati delle variabili o delle espressioni contenute nel codice. Per dichiarare esplicitamente il tipo di dati di una variabile, aggiungete al nome della variabile l'operatore due punti (:) seguito dal tipo di dati come suffisso. Per associare un tipo di dati a un parametro, utilizzate l'operatore due punti seguito dal tipo di dati. Ad esempio, il codice seguente aggiunge il tipo di dati al parametro xParam e dichiara una variabile myParam con un tipo di dati esplicito:

function runtimeTest(xParam:String) 
{ 
    trace(xParam); 
} 
var myParam:String = "hello"; 
runtimeTest(myParam);

In modalità rigorosa, il compilatore ActionScript segnala i casi di mancata corrispondenza del tipo come errori di compilazione. Ad esempio, il codice seguente dichiara un parametro di funzione xParam, del tipo Object, ma successivamente tenta di assegnare valori del tipo String e Number allo stesso parametro. In modalità rigorosa, questo codice genera un errore del compilatore.

function dynamicTest(xParam:Object) 
{ 
    if (xParam is String) 
    { 
        var myStr:String = xParam; // compiler error in strict mode 
        trace("String: " + myStr); 
    } 
    else if (xParam is Number) 
    { 
        var myNum:Number = xParam; // compiler error in strict mode 
        trace("Number: " + myNum); 
    } 
}

Anche in modalità rigorosa, tuttavia, è possibile scegliere di non eseguire la verifica del tipo in fase di compilazione non specificando il tipo sul lato destro di un'istruzione di assegnazione. Per contrassegnare una variabile o un'espressione come priva di tipo, è possibile omettere l'annotazione di tipo o utilizzare l'annotazione speciale dell'asterisco (*). Ad esempio, se il parametro xParam contenuto nel codice precedente viene modificato omettendo l'annotazione di tipo, il codice viene compilato anche in modalità rigorosa:

function dynamicTest(xParam) 
{ 
    if (xParam is String) 
    { 
        var myStr:String = xParam; 
        trace("String: " + myStr); 
    } 
    else if (xParam is Number) 
    { 
        var myNum:Number = xParam; 
        trace("Number: " + myNum); 
    } 
} 
dynamicTest(100) 
dynamicTest("one hundred");

Verifica del tipo in fase di runtime

Il controllo del tipo in fase di runtime viene eseguito in ActionScript 3.0 sia nella modalità di compilazione rigorosa che in modalità standard. Considerate una situazione in cui il valore 3 viene passato come argomento a una funzione per la quale è previsto array. In modalità rigorosa, il compilatore genera un errore perché il valore 3 non è compatibile con il tipo di dati Array. Se disattivate la modalità rigorosa e attivate la modalità standard, il compilatore non rileva la mancata corrispondenza del tipo, ma la verifica in fase di runtime genera un errore runtime.

L'esempio seguente mostra una funzione denominata typeTest() per la quale è previsto un argomento Array ma alla quale viene invece passato il valore 3. Questa situazione genera un errore runtime in modalità standard perché il valore 3 non è un membro del tipo di dati dichiarato del parametro (Array).

function typeTest(xParam:Array) 
{ 
    trace(xParam); 
} 
var myNum:Number = 3; 
typeTest(myNum);  
// run-time error in ActionScript 3.0 standard mode

In determinati casi può essere generato un errore runtime di tipo anche in modalità rigorosa. Questa situazione può verificarsi quando, pur essendo attiva la modalità rigorosa, si sceglie di non eseguire la verifica del tipo in fase di compilazione specificando una variabile senza tipo. L'uso di una variabile senza tipo non elimina la verifica del tipo, bensì la rimanda alla fase di runtime. Ad esempio, se la variabile myNum dell'esempio precedente non ha un tipo di dati dichiarato, il compilatore non è in grado di rilevare la mancata corrispondenza del tipo ma il codice genera un errore runtime perché esegue un confronto tra il valore runtime di myNum, che è impostato su 3 dall'istruzione di assegnazione, e il tipo di dati di xParam, che è Array.

function typeTest(xParam:Array) 
{ 
    trace(xParam); 
} 
var myNum = 3; 
typeTest(myNum);  
// run-time error in ActionScript 3.0

La verifica in fase di runtime consente anche un uso più flessibile dell'ereditarietà rispetto a quella in fase di compilazione. Rimandando la verifica del tipo alla fase di runtime, la modalità standard permette di fare riferimento alle proprietà di una sottoclasse anche se eseguite un upcast, ovvero utilizzate una classe di base per dichiarare il tipo di un'istanza di classe ma una sottoclasse per creare l'istanza vera e propria. Ad esempio, potete creare una classe denominata ClassBase che può essere estesa (non è possibile estendere le classi con attributo final):

class ClassBase 
{ 
}

Successivamente potete creare una sottoclasse di ClassBase denominata ClassExtender, dotata di una proprietà di nome someString, come nel codice seguente:

class ClassExtender extends ClassBase 
{ 
    var someString:String; 
}

Utilizzando entrambe le classi, è possibile definire un'istanza di classe dichiarata mediante il tipo di dati ClassBase ma creata utilizzando la funzione di costruzione ClassExtender. Un'operazione di upcast è considerata sicura perché la classe di base non contiene proprietà o metodi che non sono disponibili nella sottoclasse.

var myClass:ClassBase = new ClassExtender();

Una sottoclasse, al contrario, può contenere proprietà o metodi che non sono presenti nella rispettiva classe di base. Ad esempio, la classe ClassExtender contiene la proprietà someString, che non esiste nella classe ClassBase. Nella modalità standard di ActionScript 3.0, è possibile fare riferimento a questa proprietà usando l'istanza myClass senza generare un errore in fase di compilazione, come mostra l'esempio seguente:

var myClass:ClassBase = new ClassExtender(); 
myClass.someString = "hello"; 
// no error in ActionScript 3.0 standard mode

L'operatore is

L'operatore is consente di verificare se una variabile o un'espressione è un membro di un determinato tipo di dati. Nelle versioni precedenti di ActionScript, la stessa funzionalità era fornita dall'operatore instanceof, che tuttavia in ActionScript 3.0 non va utilizzato per verificare l'appartenenza a un tipo di dati. È necessario utilizzare l'operatore is anziché instanceof per eseguire la verifica manuale del tipo, perché l'espressione x instanceof y si limita a controllare se nella catena di prototipi di x è presente y (in ActionScript 3.0, la catena di prototipi non fornisce un quadro completo della gerarchia di ereditarietà).

L'operatore is invece esamina la gerarchia di ereditarietà effettiva e consente di verificare non solo se un oggetto è un'istanza di una particolare classe, ma anche se è un'istanza di una classe che implementa una particolare interfaccia. L'esempio seguente crea un'istanza della classe Sprite denominata mySprite e utilizza l'operatore is per verificare se mySprite è un'istanza delle classi Sprite e DisplayObject e se implementa l'interfaccia IEventDispatcher:

var mySprite:Sprite = new Sprite(); 
trace(mySprite is Sprite); // true 
trace(mySprite is DisplayObject);// true 
trace(mySprite is IEventDispatcher); // true

L'operatore is controlla la gerarchia di ereditarietà e segnala correttamente che mySprite è compatibile con le classi Sprite e DisplayObject (Sprite è una sottoclasse della classe DisplayObject). Inoltre, verifica se mySprite eredita da qualunque classe che implementa l'interfaccia IEventDispatcher. Poiché la classe Sprite eredita dalla classe EventDispatcher, che implementa l'interfaccia IEventDispatcher, l'operatore is segnala correttamente che mySprite implementa la stessa interfaccia.

Il codice dell'esempio seguente esegue gli stessi controlli di quello precedente, ma con l'operatore instanceof al posto di is. L'operatore instanceof identifica correttamente mySprite come istanza di Sprite o DisplayObject, ma restituisce false quando viene utilizzato per verificare se mySprite implementa l'interfaccia IEventDispatcher.

trace(mySprite instanceof Sprite); // true 
trace(mySprite instanceof DisplayObject);// true 
trace(mySprite instanceof IEventDispatcher); // false

L'operatore as

Anche l'operatore as consente di verificare se un'espressione è un membro di un determinato tipo di dati. A differenza di is, tuttavia, as non restituisce un valore booleano, bensì il valore dell'espressione (invece di true) oppure null (invece di false). L'esempio seguente mostra il risultato che si ottiene utilizzando l'operatore as anziché is per controllare semplicemente se un'istanza Sprite è membro dei tipi di dati DisplayObject, IEventDispatcher e Number.

var mySprite:Sprite = new Sprite(); 
trace(mySprite as Sprite);                 // [object Sprite] 
trace(mySprite as DisplayObject);                 // [object Sprite] 
trace(mySprite as IEventDispatcher);                 // [object Sprite] 
trace(mySprite as Number);                                       // null

Quando si usa l'operatore as, l'operando sulla destra deve essere un tipo di dati. Un eventuale tentativo di utilizzare un'espressione diversa da un tipo di dati come operando sulla destra produrrebbe un errore.

Classi dinamiche

Una classe dinamica definisce un oggetto che può essere alterato in fase di runtime aggiungendo o modificandone le proprietà e i metodi. Un classe non dinamica, ad esempio la classe String, si definisce chiusa (sealed in inglese). Non è possibile aggiungere proprietà o metodi a una classe chiusa in runtime.

Per creare una classe dinamica si utilizza l'attributo dynamic nella relativa dichiarazione. Ad esempio, il codice seguente crea una classe dinamica denominata Protean:

dynamic class Protean 
{ 
    private var privateGreeting:String = "hi"; 
    public var publicGreeting:String = "hello"; 
    function Protean() 
    { 
        trace("Protean instance created"); 
    } 
}

Se in seguito create un'istanza della classe Protean, potete aggiungervi proprietà o metodi esternamente alla definizione della classe. Ad esempio, il codice seguente crea un'istanza della classe Protean e vi aggiunge due proprietà denominate rispettivamente aString e aNumber:

var myProtean:Protean = new Protean(); 
myProtean.aString = "testing"; 
myProtean.aNumber = 3; 
trace(myProtean.aString, myProtean.aNumber); // testing 3

Le proprietà aggiunte a un'istanza di una classe dinamica sono entità runtime, quindi le verifiche di qualsiasi tipo vengono eseguite in fase di runtime. Non è possibile aggiungere un'annotazione di tipo a una proprietà creata in questo modo.

È anche possibile aggiungere un metodo all'istanza myProtean definendo una funzione e associandola a una proprietà dell'istanza myProtean. Il codice seguente sposta l'istruzione trace in un metodo denominato traceProtean():

var myProtean:Protean = new Protean(); 
myProtean.aString = "testing"; 
myProtean.aNumber = 3; 
myProtean.traceProtean = function () 
{ 
    trace(this.aString, this.aNumber); 
}; 
myProtean.traceProtean(); // testing 3

I metodi creati in questo modo, tuttavia, non hanno accesso a eventuali proprietà o metodi privati della classe Protean. Inoltre, anche i riferimenti a proprietà o metodi pubblici della classe Protean devono essere qualificati con la parola chiave this o con il nome della classe. Nell'esempio seguente, il metodo traceProtean() tenta di accedere alle variabili private e pubbliche della classe Protean.

myProtean.traceProtean = function () 
{ 
    trace(myProtean.privateGreeting); // undefined 
    trace(myProtean.publicGreeting); // hello 
}; 
myProtean.traceProtean();

Descrizione dei tipi di dati

I tipi di dati di base sono Boolean, int, Null, Number, String, uint e void. Le classi principali di ActionScript definiscono anche i seguenti tipi di dati complessi: Object, Array, Date, Error, Function, RegExp, XML e XMLList.

Tipo di dati Boolean

Il tipo di dati Boolean include due valori: true e false. Nessun altro valore è consentito per le variabili di questo tipo. Il valore predefinito di una variabile Boolean dichiarata ma non inizializzata è false.

Tipo di dati int

Il tipo di dati int è memorizzato internamente come numero intero a 32 bit e include la serie di numeri interi da

-2.147.483.648 (-231) a 2.147.483.647 (231 - 1). Le versioni precedenti di ActionScript offrivano solo il tipo di dati Number, utilizzato sia per i numeri interi che per quelli a virgola mobile. In ActionScript 3.0 è ora possibile accedere ai tipi macchina di basso livello per i numeri interi a 32 bit con e senza segno. Se la variabile non deve usare numeri a virgola mobile, l'impiego del tipo di dati int al posto di Number garantisce maggiore velocità ed efficienza.

Per i numeri interi al di fuori dell'intervallo dei valori minimo e massimo, utilizzate il tipo di dati Number, che è in grado di gestire i valori compresi tra -9.007.199.254.740.992 e 9.007.199.254.740.992 (valori interi a 53 bit). Il valore predefinito per le variabili del tipo di dati int è 0.

Tipo di dati Null

Il tipo di dati Null contiene un solo valore, null. Questo è il valore predefinito per il tipo di dati String e per tutte le classi che definiscono tipi di dati complessi, compresa la classe Object. Nessuno degli altri tipi di dati di base, come Boolean, Number, int e uint, contiene il valore null. In fase di runtime, il valore null viene convertito nel valore predefinito appropriato se tentate di assegnare null a variabili di tipo Boolean, Number, int o uint. Non è possibile utilizzare questo tipo di dati come annotazione di tipo.

Tipo di dati Number

In ActionScript 3.0, il tipo di dati Number può rappresentare numeri interi, numeri interi senza segno e numeri a virgola mobile. Tuttavia, per ottimizzare le prestazioni, è meglio utilizzare il tipo di dati Number solo per i numeri interi maggiori dei numeri a 32 bit memorizzabili dai tipi int e uint, oppure per i numeri a virgola mobile. Per memorizzare un numero a virgola mobile, includete il punto dei decimali nel numero. Se omettete il punto dei decimali, il valore viene memorizzato come numero intero.

Il tipo di dati Number utilizza il formato a doppia precisione a 64 bit specificato dallo standard IEEE 754 per i calcoli aritmetici binari a virgola mobile, che prescrive come devono essere memorizzati i numeri a virgola mobile utilizzando i 64 bit disponibili. Un bit serve per designare il numero come positivo o negativo, undici bit sono utilizzati per l'esponente (memorizzato come base 2) e i rimanenti 52 bit servono per memorizzare il significante (chiamato anche mantissa), ovvero il numero che viene elevato alla potenza indicata dall'esponente.

Utilizzando alcuni dei bit per memorizzare un esponente, il tipo di dati Number può memorizzare numeri a virgola mobile notevolmente più grandi che non se utilizzasse tutti i bit per il significante. Ad esempio, se il tipo di dati Number utilizzasse tutti i 64 bit per memorizzare il significante, il numero più grande che potrebbe memorizzare sarebbe 265 - 1. Utilizzando 11 bit per memorizzare un esponente, il tipo di dati Number può elevare il significante fino a una potenza di 1023.

I valori massimo e minimo che il tipo Number può rappresentare sono memorizzati in proprietà statiche della classe Number denominate Number.MAX_VALUE e Number.MIN_VALUE.

Number.MAX_VALUE == 1.79769313486231e+308 
Number.MIN_VALUE == 4.940656458412467e-324

Un intervallo di numeri così ampio va a scapito della precisione. Il tipo di dati Number utilizza 52 bit per memorizzare il significante, con il risultato che i numeri che richiedono più di 52 bit per essere rappresentati con precisione, ad esempio la frazione 1/3, sono solo approssimazioni. Se l'applicazione richiede una precisione assoluta per i numeri decimali, è necessario utilizzare un software in grado di implementare i calcoli aritmetici a virgola mobile decimali anziché quelli binari.

Quando memorizzate valori interi con il tipo di dati Number, vengono utilizzati solo i 52 bit del significante. Il tipo di dati Number usa questi 52 bit e un bit speciale nascosto per rappresentare i numeri interi da -9.007.199.254.740.992 (-253) a 9.007.199.254.740.992 (253).

Il valore NaN non solo è il valore predefinito per le variabili di tipo Number, ma è anche il risultato di qualunque operazione che deve restituire un numero e invece restituisce un valore diverso. Ad esempio, se tentate di calcolare la radice quadrata di un numero negativo, il risultato è NaN. Altri valori Number speciali sono infinito positivo e infinito negativo.

Nota: il risultato della divisione per 0 è NaN solo se anche il divisore è 0. La divisione per 0 dà il risultato infinito se il dividendo è positivo oppure -infinito se è negativo.

Tipo di dati String

Il tipo di dati String rappresenta una sequenza di caratteri a 16 bit. Le stringhe vengono memorizzate internamente come caratteri Unicode, utilizzando il formato UTF-16. Come nel linguaggio di programmazione Java, le stringhe sono valori immutabili. Un'operazione su un valore String restituisce una nuova istanza della stringa. Il valore predefinito di una variabile dichiarata con il tipo di dati String è null. Il valore null non è equivalente a una stringa vuota (""). Il valore null indica che la variabile non contiene alcun valore, mentre la stringa vuota indica che il valore della variabile è un tipo String che non contiene nessun carattere.

Tipo di dati uint

Il tipo di dati uint è memorizzato internamente come numero intero a 32 bit senza segno e include la serie di numeri interi da 0 a 4.294.967.295 (232 - 1). Utilizzate il tipo di dati uint in circostanze speciali che richiedono numeri interi non negativi. Ad esempio, va necessariamente utilizzato per rappresentare i valori di colore dei pixel, perché il tipo di dati int ha un bit di segno interno che non è appropriato per la gestione dei valori di colore. Per i numeri interi maggiori del valore uint massimo, utilizzate il tipo di dati Number, che è in grado di gestire i valori interi a 53 bit. Il valore predefinito per le variabili del tipo di dati uint è 0.

Tipo di dati void

Il tipo di dati void contiene un solo valore, undefined. Nelle versioni precedenti di ActionScript, undefined era il valore predefinito per le istanze della classe Object. In ActionScript 3.0, il valore predefinito delle istanze Object è null. Se tentate di assegnare il valore undefined a un'istanza della classe Object, il valore viene convertito in null. È possibile assegnare il valore undefined solo alle variabili senza tipo, ovvero quelle che sono prive di un'annotazione di tipo oppure utilizzano l'asterisco (*) come annotazione. Potete utilizzare void solo come annotazione del tipo restituito.

Tipo di dati Object

Il tipo di dati Object è definito dalla classe Object che viene utilizzata come classe di base per tutte le definizioni di classe in ActionScript. La versione ActionScript 3.0 del tipo di dati Object differisce dalle versioni precedenti per tre aspetti. Innanzi tutto, il tipo di dati Object non è più il tipo predefinito assegnato alle variabili prive di annotazione di tipo. In secondo luogo, il tipo Object non include più il valore undefined, che era il valore predefinito di tutte le istanze Object. Infine, in ActionScript 3.0 il valore predefinito delle istanze della classe Object è null.

Nelle versioni precedenti di ActionScript, a una variabile priva di annotazione di tipo veniva assegnato automaticamente il tipo di dati Object. ActionScript 3.0, al contrario, prevede la possibilità di variabili effettivamente prive di tipo. Pertanto, le variabili per le quali non viene fornita un'annotazione di tipo vengono ora considerate senza tipo. Se preferite rendere esplicito a chi leggerà il codice che la vostra intenzione è effettivamente quella di lasciare una variabile priva di tipo, potete utilizzare il simbolo di asterisco (*) come annotazione di tipo, che equivale a omettere l'annotazione. L'esempio seguente mostra due istruzioni equivalenti, che dichiarano entrambe una variabile senza tipo x:

var x 
var x:*

Solo le variabili senza tipo possono contenere il valore undefined. Se tentate di assegnare il valore undefined a una variabile che appartiene a un tipo di dati, il runtime converte il valore undefined nel valore predefinito del tipo di dati in questione. Per le istanze del tipo di dati Object, il valore predefinito è null. Pertanto, se tentate di assegnare undefined a un'istanza Object il valore viene convertito in null.

Conversione del tipo di dati

Una conversione del tipo di dati ha luogo quando un valore viene trasformato in un valore appartenente a un tipo di dati diverso. Le conversioni di tipo possono essere implicite o esplicite. Una conversione implicita, chiamata anche assegnazione forzata (in inglese, coercion), viene talvolta eseguita in fase di runtime. Ad esempio, se il valore 2 è assegnato a una variabile del tipo di dati Boolean, il valore 2 viene convertito nel valore booleano true prima che il valore venga assegnato alla variabile. La conversione esplicita, chiamata anche inserimento (in inglese, casting), ha luogo quando il codice passa al compilatore l'istruzione di elaborare una variabile di un tipo di dati particolare come se appartenesse a un tipo di dati diverso. Quando l'operazione riguarda valori di base, l'inserimento ha effettivamente il risultato di convertire i valori da un tipo di dati a un altro. Per inserire un oggetto in un tipo diverso, occorre racchiudere il nome dell'oggetto tra parentesi e farlo precedere dal nome del nuovo tipo. Il codice seguente, ad esempio accetta un valore booleano e lo inserisce in un numero intero:

var myBoolean:Boolean = true; 
var myINT:int = int(myBoolean); 
trace(myINT); // 1

Conversione implicita

La conversione implicita viene eseguita in fase di runtime in una serie di casi:

  • Nelle istruzioni di assegnazione

  • Quando i valori vengono passati come argomenti di funzioni

  • Quando i valori vengono restituiti da funzioni

  • Nelle espressioni che utilizzano determinati operatori, ad esempio l'operatore di addizione (+)

    Per i tipi definiti dall'utente, la conversione implicita ha luogo quando il valore da convertire è un'istanza della classe di destinazione o di una classe derivata da essa. Se una conversione implicita ha esito negativo, viene generato un errore. Ad esempio, il codice seguente contiene una conversione implicita corretta e una con esito negativo:

    class A {} 
    class B extends A {} 
     
    var objA:A = new A(); 
    var objB:B = new B(); 
    var arr:Array = new Array(); 
     
    objA = objB; // Conversion succeeds. 
    objB = arr; // Conversion fails.

    Per i tipi di base, le conversioni implicite vengono gestite chiamando gli stessi algoritmi di conversione interni che vengono chiamati dalle funzioni di conversione esplicita.

Conversione esplicita

È utile ricorrere alla conversione esplicita (detta anche inserimento o casting) quando compilate il codice in modalità rigorosa, in particolare quando volete evitare che una mancata corrispondenza di tipo generi un errore in fase di compilazione. Questa situazione può verificarsi quando si ha la certezza che i valori saranno convertiti correttamente in fase di runtime mediante l'assegnazione forzata. Ad esempio, quando utilizzate i dati ricevuti da un form, potete scegliere di ricorrere all'assegnazione forzata per convertire determinati valori di stringa in valori numerici. Il codice seguente genera un errore di compilazione anche se, in modalità standard, verrebbe eseguito senza problemi.

var quantityField:String = "3"; 
var quantity:int = quantityField; // compile time error in strict mode

Se desiderate continuare a utilizzare la modalità rigorosa ma volete convertire la stringa in numero intero, potete utilizzare la conversione esplicita, come nell'esempio seguente:

var quantityField:String = "3"; 
var quantity:int = int(quantityField); // Explicit conversion succeeds.

Inserimento nei tipi int, uint e Number

Potete inserire qualunque tipo di dati nei tre seguenti tipi numerici: int, uint e Number. Se per vari motivi il numero non può essere convertito, il valore predefinito 0 viene assegnato ai tipi di dati int e uint, mentre il valore predefinito NaN viene assegnato al tipo di dati Number. Se convertite un valore booleano in numero, true diventa 1 e false diventa 0.

var myBoolean:Boolean = true; 
var myUINT:uint = uint(myBoolean); 
var myINT:int = int(myBoolean); 
var myNum:Number = Number(myBoolean); 
trace(myUINT, myINT, myNum); // 1 1 1 
myBoolean = false; 
myUINT = uint(myBoolean); 
myINT = int(myBoolean); 
myNum = Number(myBoolean); 
trace(myUINT, myINT, myNum); // 0 0 0

I valori stringa che contengono solo cifre possono essere convertiti correttamente in uno dei tre tipi numerici, i quali consentono inoltre di convertire stringhe che assomigliano a numeri negativi o che rappresentano un valore esadecimale (ad esempio, 0x1A). Il processo di conversione ignora gli eventuali caratteri di spazio vuoto presenti all'inizio e alla fine del valore stringa. È anche possibile convertire le stringhe che hanno l'aspetto di numeri a virgola mobile utilizzando Number(). Se viene incluso il punto dei decimali, uint() e int() restituiscono un numero intero in cui i caratteri che seguono il punto sono troncati. Ad esempio, i valori stringa seguenti possono essere inseriti in valori numerici:

trace(uint("5")); // 5 
trace(uint("-5")); // 4294967291. It wraps around from MAX_VALUE 
trace(uint(" 27 ")); // 27 
trace(uint("3.7")); // 3 
trace(int("3.7")); // 3 
trace(int("0x1A")); // 26 
trace(Number("3.7")); // 3.7

I valori stringa che contengono caratteri non numerici restituiscono 0 se vengono convertiti con int() o uint() oppure NaN se convertiti con Number(). Il processo di conversione ignora lo spazio vuoto all'inizio e alla fine, ma restituisce 0 o NaN se una stringa contiene uno spazio vuoto tra due numeri.

trace(uint("5a")); // 0 
trace(uint("ten")); // 0 
trace(uint("17 63")); // 0

In ActionScript 3.0, la funzione Number() non supporta più gli ottali, ovvero i numeri a base 8. Se passate una stringa con uno zero iniziale alla funzione Number() di ActionScript 2.0, il numero viene interpretato come ottale e convertito nell'equivalente decimale. Lo stesso non vale per la funzione Number() di ActionScript 3.0, che invece ignora lo zero iniziale. Ad esempio, il codice seguente genera un output diverso se viene compilato con versioni differenti di ActionScript:

trace(Number("044"));  
// ActionScript 3.0 44 
// ActionScript 2.0 36

L'inserimento non è necessario quando un valore di un tipo numerico viene assegnato a una variabile di un altro tipo numerico. Anche in modalità rigorosa, i tipi numerici vengono convertiti implicitamente in altri tipi numerici. Ciò significa che in alcuni casi potete ottenere valori imprevisti quando viene superato l'intervallo di un tipo numerico. Gli esempi seguenti vengono compilati correttamente in modalità rigorosa, ma alcuni di essi generano valori imprevisti:

var myUInt:uint = -3; // Assign int/Number value to uint variable 
trace(myUInt); // 4294967293 
 
var myNum:Number = sampleUINT; // Assign int/uint value to Number variable 
trace(myNum) // 4294967293 
 
var myInt:int = uint.MAX_VALUE + 1; // Assign Number value to uint variable 
trace(myInt); // 0 
 
myInt = int.MAX_VALUE + 1; // Assign uint/Number value to int variable 
trace(myInt); // -2147483648

La tabella che segue riepiloga i risultati dell'inserimento nei tipi Number, int o uint da altri tipi di dati.

Tipo di dati o valore

Risultato della conversione in Number, int o uint

Boolean

Se il valore è true, 1; altrimenti, 0.

Date

La rappresentazione interna dell'oggetto Date, che corrisponde al numero di millisecondi trascorsi dalla mezzanotte del 1 gennaio 1970 (ora universale).

null

0

Object

Se l'istanza è null e viene convertita in Number, NaN; altrimenti, 0.

String

Un numero se la stringa può essere convertita in un numero; in caso contrario, NaN viene convertito in Number o 0 nel caso di conversione in int o uint.

undefined

Se convertito in Number, NaN; se convertito in int o uint, 0.

Inserimento nel tipo Boolean

L'inserimento di un tipo di dati numerico (uint, int o Number) nel tipo Boolean restituisce false se il valore numerico è 0 e true in tutti gli altri casi. Per il tipo di dati Number, anche il valore NaN restituisce false. L'esempio seguente illustra i risultati di un inserimento dei numeri -1, 0 e 1:

var myNum:Number; 
for (myNum = -1; myNum<2; myNum++) 
{ 
    trace("Boolean(" + myNum +") is " + Boolean(myNum)); 
}

L'output dell'esempio mostra che dei tre numeri solo 0 restituisce il valore false:

Boolean(-1) is true 
Boolean(0) is false 
Boolean(1) is true

L'inserimento di un valore String nel tipo Boolean restituisce false se la stringa è null o vuota ("") e true in tutti gli altri casi.

var str1:String; // Uninitialized string is null. 
trace(Boolean(str1)); // false 
 
var str2:String = ""; // empty string 
trace(Boolean(str2)); // false 
 
var str3:String = " "; // white space only 
trace(Boolean(str3)); // true

L'inserimento di un'istanza della classe Object nel tipo Boolean restituisce false se l'istanza è null e true in tutti gli altri casi:

var myObj:Object; // Uninitialized object is null. 
trace(Boolean(myObj)); // false 
 
myObj = new Object(); // instantiate  
trace(Boolean(myObj)); // true

Le variabili Boolean vengono elaborate in un modo speciale in modalità rigorosa, ovvero è possibile assegnare valori di qualunque tipo di dati a una variabile Boolean senza eseguire l'inserimento. L'assegnazione forzata implicita da tutti i tipi di dati al tipo Boolean viene eseguita anche in modalità rigorosa. In altri termini, contrariamente a quasi tutti gli altri tipi di dati, l'inserimento nel tipo Boolean non è necessario per evitare gli errori della modalità rigorosa. Gli esempi seguenti vengono compilati correttamente in modalità rigorosa e danno i risultati previsti anche in fase di runtime:

var myObj:Object = new Object(); // instantiate  
var bool:Boolean = myObj; 
trace(bool); // true 
bool = "random string"; 
trace(bool); // true 
bool = new Array(); 
trace(bool); // true 
bool = NaN; 
trace(bool); // false

La tabella che segue riepiloga i risultati dell'inserimento nel tipo Boolean da altri tipi di dati.

Tipo di dati o valore

Risultato della conversione in Boolean

String

false se il valore è null o una stringa vuota (""); true negli altri casi.

null

false

Number, int o uint

false se il valore è NaN o 0; true negli altri casi.

Object

false se l'istanza è null; true negli altri casi.

Inserimento nel tipo String

L'inserimento di un tipo di dati numerico nel tipo di dati String restituisce una rappresentazione del numero sotto forma di stringa. Se invece inserite un valore booleano nel tipo di dati String, viene restituita la stringa "true" se il valore è true e la stringa "false" se il valore è false.

Se inserite un'istanza della classe Object nel tipo di dati String, viene restituita la stringa "null" se l'istanza è null. In tutti gli altri casi, l'inserimento della classe Object nel tipo di dati String restituisce la stringa "[object Object]" .

Quando inserite un'istanza della classe Array nel tipo String, viene restituita una stringa composta da un elenco delimitato da virgole di tutti gli elementi dell'array. Ad esempio, il seguente inserimento nel tipo di dati String restituisce una sola stringa contenente tutti e tre gli elementi dell'array:

var myArray:Array = ["primary", "secondary", "tertiary"]; 
trace(String(myArray)); // primary,secondary,tertiary

Se inserite un'istanza della classe Date nel tipo di dati String, viene restituita una rappresentazione della data contenuta nell'istanza sotto forma di stringa. Ad esempio, il codice seguente restituisce una rappresentazione sotto forma di stringa dell'istanza della classe Date. L'output mostra i risultati per l'ora legale del Pacifico:

var myDate:Date = new Date(2005,6,1); 
trace(String(myDate)); // Fri Jul 1 00:00:00 GMT-0700 2005

La tabella che segue riepiloga i risultati dell'inserimento nel tipo String da altri tipi di dati.

Tipo di dati o valore

Risultato della conversione in String

Array

Una stringa composta da tutti gli elementi dell'array.

Boolean

"true" o "false"

Date

La rappresentazione in formato stringa dell'oggetto Date.

null

"null"

Number, int o uint

La rappresentazione in formato stringa del numero.

Object

Se l'istanza è null, "null"; negli altri casi, "[object Object]".