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 (-2
31
) a 2.147.483.647 (2
31
- 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 2
65
- 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 (-2
53
) a 9.007.199.254.740.992 (2
53
).
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 (2
32
- 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]".
|
|
|
|