Classi

Una classe è una rappresentazione astratta di un oggetto. In una classe sono memorizzate informazioni sui tipi di dati che un oggetto può contenere e sui comportamenti in base ai quali un oggetto può funzionare. L'utilità di tale astrazione non è necessariamente evidente quando si creano brevi script contenenti solo pochi oggetti che interagiscono tra loro. Tuttavia, con l'ampliarsi dell'area di validità di un programma aumenta anche il numero di oggetti da gestire. In tal caso, le classi consentono di controllare più accuratamente la creazione degli oggetti e il modo in cui essi interagiscono tra loro.

Fino alla versione di ActionScript 1.0, i programmatori potevano utilizzare gli oggetti funzione per creare costrutti somiglianti a classi. Con ActionScript 2.0 è stato introdotto il supporto delle classi con parole chiave quali class ed extends. In ActionScript 3.0, non solo è previsto il supporto delle parole chiave introdotte in ActionScript 2.0, ma vengono introdotte anche nuove funzionalità. Ad esempio, ActionScript 3.0 include il controllo dell'accesso ottimizzato mediante gli attributi protected e internal. Inoltre, fornisce un migliore controllo dell'ereditarietà grazie all'uso delle parole chiave final e override.

Per gli sviluppatori che hanno già esperienza nella creazione di classi con linguaggi di programmazione quali Java, C++ o C#, le procedure di ActionScript risulteranno familiari. ActionScript utilizza infatti molte parole chiave e nomi di attributo comuni a tali linguaggi di programmazione, ad esempio class, extends e public.

Nota: nella documentazione Adobe ActionScript, il termine proprietà si riferisce a qualsiasi membro di una classe o di un oggetto, incluse variabili, costanti e metodi. Inoltre, anche se spesso i termini classe e statica vengono utilizzati in modo intercambiabile, in questo capitolo essi si riferiscono a concetti distinti. Ad esempio, il termine “proprietà di classe” indica tutti i membri di una classe e non solo i membri statici.

Definizioni delle classi

Le definizioni delle classi in ActionScript 3.0 impiegano una sintassi simile a quella utilizzata in ActionScript 2.0. La sintassi corretta per la definizione di una classe richiede la parola chiave class seguita dal nome della classe. Il corpo della classe, racchiuso tra parentesi graffe ({}), segue il nome della classe. Ad esempio, il seguente codice consente di creare una classe denominata Shape contenente una variabile denominata visible:

public class Shape 
{ 
    var visible:Boolean = true; 
}

Una modifica significativa della sintassi riguarda la definizione delle classi che si trovano all'interno di un pacchetto. In ActionScript 2.0, se una classe si trovava all'interno di un pacchetto, il nome del pacchetto doveva essere incluso nella dichiarazione della classe. In ActionScript 3.0, con l'introduzione dell'istruzione package, il nome del pacchetto deve essere incluso nella dichiarazione del pacchetto, anziché nella dichiarazione della classe. Ad esempio, le seguenti dichiarazioni di classe mostrano come la classe BitmapData, che fa parte del pacchetto flash.display, viene definita in ActionScript 2.0 e in ActionScript 3.0:

// ActionScript 2.0 
class flash.display.BitmapData {} 
 
// ActionScript 3.0 
package flash.display 
{ 
    public class BitmapData {} 
}

Attributi di classe

ActionScript 3.0 consente di modificare le definizioni delle classi mediante l'impiego di uno dei seguenti attributi:

Attributo

Definizione

dynamic

Consente di aggiungere proprietà alle istanze in fase di runtime.

final

La classe non può essere estesa da un'altra classe.

internal (valore predefinito)

Visibile ai riferimenti che si trovano all'interno del pacchetto corrente.

public

Visibile a tutti i riferimenti.

In tutti questi casi, a eccezione di internal, dovete includere espressamente l'attributo per ottenere il comportamento associato. Ad esempio, se la definizione di una classe non include l'attributo dynamic, non è possibile aggiungere proprietà a un'istanza della classe in fase di runtime. Per assegnare esplicitamente un attributo dovete collocarlo all'inizio della definizione della classe, come indicato nel codice seguente:

dynamic class Shape {}

Tenete presente che nell'elenco non è incluso un attributo denominato abstract. Le classi abstract non sono supportate in ActionScript 3.0. Notate inoltre che l'elenco non contiene attributi denominati private e protected. Tali attributi hanno un significato unicamente all'interno di una definizione di classe e non possono essere applicati alle classi stesse. Per fare in modo che una classe non sia pubblicamente visibile al di fuori di un pacchetto, è necessario inserire la classe in un pacchetto e contrassegnarla con l'attributo internal. In alternativa, potete omettere sia l'attributo internal che l'attributo public; in tal modo il compilatore aggiunge automaticamente l'attributo internal. Potete anche definire una classe in modo che sia visibile solo all'interno del file di origine in cui è definita. Collocate la classe alla base del file sorgente, sotto la parentesi graffa che chiude la definizione del pacchetto.

Corpo della classe

Il corpo della classe, racchiuso tra parentesi graffe, consente di definire le variabili, le costanti e i metodi della classe. L'esempio seguente mostra la dichiarazione della classe Accessibility in ActionScript 3.0:

public final class Accessibility 
{ 
    public static function get active():Boolean; 
    public static function updateProperties():void; 
}

All'interno del corpo di una classe è possibile definire anche uno spazio dei nomi. Nell'esempio seguente è illustrato come uno spazio dei nomi può essere definito all'interno del corpo di una classe e utilizzato come attributo di un metodo di tale classe:

public class SampleClass 
{ 
    public namespace sampleNamespace; 
    sampleNamespace function doSomething():void; 
}

ActionScript 3.0 consente di inserire nel corpo di una classe non solo definizioni, ma anche istruzioni. Le istruzioni che si trovano all'interno del corpo di una classe, ma al di fuori della definizione di un metodo, vengono eseguite una sola volta, vale a dire nel momento in cui la definizione della classe viene rilevata la prima volta e l'oggetto classe associato viene creato. L'esempio seguente include una chiamata a una funzione esterna, hello(), e un'istruzione trace che consente di produrre un messaggio di conferma quando la classe viene definita:

function hello():String 
{ 
    trace("hola"); 
} 
class SampleClass 
{ 
    hello(); 
    trace("class created"); 
} 
// output when class is created 
hola 
class created

In ActionScript 3.0 è consentito definire una proprietà statica e una proprietà di istanza con lo stesso nome all'interno di un medesimo corpo di classe. Ad esempio, il codice seguente indica una variabile statica denominata message e una variabile di istanza con lo stesso nome:

class StaticTest 
{ 
    static var message:String = "static variable"; 
    var message:String = "instance variable"; 
} 
// In your script 
var myST:StaticTest = new StaticTest(); 
trace(StaticTest.message); // output: static variable 
trace(myST.message); // output: instance variable

Attributi delle proprietà di classe

In relazione al modello a oggetti di ActionScript, il termine proprietà si riferisce a un qualsiasi membro di un una classe, incluse variabili, costanti e metodi. Tuttavia, in Adobe ActionScript 3.0 Reference for the Adobe Flash Platform (Guida di riferimento di Adobe ActionScript 3.0 per la piattaforma Adobe Flash) il termine viene invece utilizzato in senso più ristretto. In tale contesto, il termine proprietà include unicamente membri di classi corrispondenti a variabili o definiti mediante il metodo getter o setter. In ActionScript 3.0 è disponibile una serie di attributi utilizzabili con qualsiasi proprietà di classe. La tabella seguente riporta tali attributi.

Attributo

Definizione

internal (valore predefinito)

Visibile ai riferimenti che si trovano all'interno dello stesso pacchetto.

private

Visibile ai riferimenti che si trovano all'interno della stessa classe.

protected

Visibile ai riferimenti che si trovano all'interno della stessa classe e delle classi derivate.

public

Visibile a tutti i riferimenti.

static

Specifica che una proprietà appartiene alla classe e non alle sue istanze.

UserDefinedNamespace

Nome dello spazio dei nomi personalizzato definito dall'utente.

Attributi dello spazio dei nomi per il controllo dell'accesso

ActionScript 3.0 prevede quattro attributi speciali che controllano l'accesso alle proprietà definite all'interno di una classe: public, private, protected e internal.

L'attributo public rende una proprietà visible in qualsiasi punto dello script. Ad esempio, per rendere un metodo disponibile al codice che si trova al di fuori del pacchetto, dovete dichiarare il metodo con l'attributo public. Ciò vale per qualsiasi proprietà che sia stata dichiarata utilizzando le parole chiave var, const o function.

L'attributo private rende una proprietà visibile unicamente ai chiamanti entro la classe che definisce le proprietà. Tale comportamento si differenzia da quello dell'attributo private di ActionScript 2.0, che consentiva a una sottoclasse di accedere a una proprietà privata di una superclasse. Un'altra significativa modifica nel comportamento ha a che fare con l'accesso in fase di runtime. In ActionScript 2.0 la parola chiave private impediva l'accesso solo in fase di compilazione e poteva essere facilmente evitata in fase di runtime. In ActionScript 3.0 ciò non è più possibile. Le proprietà contrassegnate come private non risultano disponibili né in fase di compilazione né in fase di runtime.

Ad esempio, il codice seguente crea una semplice classe denominata PrivateExample con una variabile private, quindi tenta di accedere alla variabile privata dall'esterno della classe.

class PrivateExample 
{ 
    private var privVar:String = "private variable"; 
} 
 
var myExample:PrivateExample = new PrivateExample(); 
trace(myExample.privVar);// compile-time error in strict mode 
trace(myExample["privVar"]); // ActionScript 2.0 allows access, but in ActionScript 3.0, this is a run-time error. 

In ActionScript 3.0, il tentativo di accedere a una proprietà privata mediante l'operatore punto (myExample.privVar) provoca un errore di compilazione, se ci si trova in modalità rigorosa. In caso contrario, l'errore viene riportato in fase di runtime, esattamente come accade quando si usa l'operatore di accesso alle proprietà (myExample["privVar"]).

Nella tabella seguente sono riportati i risultati dei tentativi di accesso a una proprietà privata appartenente a una classe chiusa (non dinamica):

 

Modalità rigorosa

Modalità standard

operatore punto (.)

errore di compilazione

errore di runtime

operatore parentesi ([])

errore di runtime

errore di runtime

Nelle classi dichiarate con l'attributo dynamic, i tentativi di accesso a una variabile privata non provocano errori di runtime. La variabile non è invece visibile, per cui viene restituito il valore undefined. Un errore in fase di compilazione si verifica invece se si utilizza un operatore punto in modalità rigorosa. L'esempio seguente è uguale a quello precedente, con la sola differenza che la classe PrivateExample viene dichiarata come classe dinamica:

dynamic class PrivateExample 
{ 
    private var privVar:String = "private variable"; 
} 
 
var myExample:PrivateExample = new PrivateExample(); 
trace(myExample.privVar);// compile-time error in strict mode 
trace(myExample["privVar"]); // output: undefined

Le classi dinamiche restituiscono in genere il valore undefined, anziché generare un errore, se un codice esterno alla classe tenta di accedere a una proprietà privata. Nella tabella seguente si evidenzia che l'errore viene generato unicamente se si utilizza l'operatore punto per accedere a una proprietà privata in modalità rigorosa:

 

Modalità rigorosa

Modalità standard

operatore punto (.)

errore di compilazione

undefined

operatore parentesi ([])

undefined

undefined

L'attributo protected, nuovo in ActionScript 3.0, rende una proprietà visibile ai chiamanti della sua stessa classe o di una sottoclasse. In altre parole, una proprietà protetta è disponibile solo all'interno della propria classe o delle classi che si trovano sotto di essa nella gerarchia di ereditarietà. Ciò vale sia che la sottoclasse si trovi nello stesso pacchetto o in un pacchetto differente.

Questa funzionalità è analoga all'attributo private in ActionScript 2.0. Anche l'attributo protected di ActionScript 3.0 è simile all'attributo Java protected, ma, a differenza della versione Java, consente l'accesso anche ai chiamanti all'interno dello stesso pacchetto. L'attributo protected è utile se si dispone di una variabile o di un metodo necessario alle sottoclassi, ma che si desidera tenere nascosto da codice esterno alla catena di ereditarietà.

L'attributo internal, nuovo in ActionScript 3.0, rende una proprietà visibile ai chiamanti che si trovano all'interno del suo stesso pacchetto. Si tratta dell'attributo predefinito del codice all'interno di un pacchetto e può essere applicato a qualsiasi proprietà che non presenta alcuno dei seguenti attributi:

  • public

  • private

  • protected

  • uno spazio dei nomi definito dall'utente

L'attributo internal è simile al controllo dell'accesso predefinito in Java, anche se in Java non esiste un nome esplicito per tale livello di accesso, che può essere ottenuto solo mediante l'omissione di un qualsiasi altro modificatore dell'accesso. L'attributo internal di ActionScript 3.0 consente all'utente di dimostrare esplicitamente l'intenzione di rendere una proprietà visibile unicamente ai chiamanti che si trovano all'interno del suo stesso pacchetto.

Attributo static

L'attributo static, utilizzabile con proprietà dichiarate con le parole chiave var, const o function, consente di associare una proprietà alla classe anziché a istanze della classe. Il codice esterno alla classe deve chiamare proprietà statiche utilizzando il nome della classe anziché il nome di un'istanza.

Le proprietà statiche non vengono ereditate dalle sottoclassi, ma fanno parte della catena delle aree di validità di una sottoclasse. In altre parole, all'interno del corpo di una sottoclasse, è possibile utilizzare una variabile o un metodo senza fare riferimento alla classe in cui sono stati creati.

Attributi spazio dei nomi definiti dall'utente

In alternativa agli attributi di controllo dell'accesso predefiniti, è possibile creare uno spazio dei nomi personalizzato da utilizzare come attributo. Per definizione è possibile utilizzare un solo attributo spazio dei nomi e non è possibile utilizzare tale attributo in combinazione con un qualsiasi attributo di controllo dell'accesso (public, private, protected, internal).

Variabili

Le variabili possono essere dichiarate con le parole chiave var o const. I valori delle variabili dichiarate con la parola chiave var possono essere modificati più volte durante l'esecuzione di uno script. Le variabili dichiarate con la parola chiave const sono dette costanti e ad esse possono essere assegnati valori una sola volta. Se tentate di assegnare un nuovo valore a una costante inizializzata, si verifica un errore.

Variabili statiche

Le variabili statiche vengono dichiarate utilizzando una combinazione della parola chiave static e dell'istruzione var o const. Le variabili statiche che vengono associate a una classe, anziché all'istanza di una classe, sono utili per memorizzare e condividere informazioni applicabili a un'intera classe di oggetti. Ad esempio, è appropriato l'impiego di una variabile statica per registrare quante volte viene creata un'istanza di una determinata classe oppure per memorizzare il numero massimo di istanze di una classe consentito.

Nell'esempio seguente viene creata una variabile totalCount per registrare il numero di volte in cui viene creata l'istanza di una classe e una costante MAX_NUM per memorizzare il numero massimo di istanze consentite. Le variabili totalCount e MAX_NUM sono statiche, in quanto contengono valori applicabili all'intera classe e non a una sua particolare istanza.

class StaticVars 
{ 
    public static var totalCount:int = 0; 
    public static const MAX_NUM:uint = 16; 
}

Il codice esterno alla classe StaticVars e alle sue sottoclassi può fare riferimento alle proprietà totalCount e MAX_NUM solo attraverso la classe stessa. Ad esempio, il codice seguente funziona:

trace(StaticVars.totalCount); // output: 0 
trace(StaticVars.MAX_NUM); // output: 16

Non è possibile accedere a variabili statiche attraverso un'istanza della classe; il codice seguente restituisce degli errori:

var myStaticVars:StaticVars = new StaticVars(); 
trace(myStaticVars.totalCount); // error 
trace(myStaticVars.MAX_NUM); // error

Le variabili dichiarate sia con la parola chiave static che const devono essere inizializzate nel momento in cui viene dichiarata la costante, come avviene all'interno della classe StaticVars per MAX_NUM. Non è possibile assegnare un valore a MAX_NUM all'interno della funzione di costruzione o di un metodo di istanza. Il codice seguente genera un errore in quanto non è un metodo valido per inizializzare una costante statica:

// !! Error to initialize static constant this way 
class StaticVars2 
{ 
    public static const UNIQUESORT:uint; 
    function initializeStatic():void 
    { 
        UNIQUESORT = 16; 
    } 
}

Variabili di istanza

Le variabili di istanza includono proprietà dichiarate con le parole chiave var e const, ma senza la parola chiave static. Le variabili di istanza associate a istanze di classe, anziché a un'intera classe, sono utili per la memorizzazione di valori specifici di una particolare istanza. Ad esempio, la classe Array presenta una proprietà di istanza denominata length nella quale è memorizzato il numero di elementi di array contenuti in una particolare istanza della classe Array.

Le variabili di istanza, dichiarate sia con la parola chiave var che const, non possono essere sovrascritte all'interno di una sottoclasse. È tuttavia possibile ottenere una funzionalità analoga sostituendo i metodi getter e setter.

Metodi

I metodi sono funzioni che fanno parte di una definizione di classe. Una volta creata un'istanza della classe, un metodo viene associato a tale istanza. A differenza delle funzioni dichiarate all'esterno delle classi, i metodi possono essere utilizzati esclusivamente dall'istanza alla quale sono associati.

I metodi vengono definiti utilizzando la parola chiave function. Come avviene con qualsiasi proprietà delle classi, potete applicare uno degli attributi delle proprietà della classe ai metodi, inclusi spazi dei nomi privati, protetti, pubblici, interni, statici o personalizzati. Potete utilizzare un'istruzione di funzione quale la seguente:

public function sampleFunction():String {}

Oppure potete utilizzare una variabile alla quale viene assegnata un'espressione della funzione, come nell'esempio seguente:

public var sampleFunction:Function = function () {}

Nella maggior parte dei casi, si consiglia di utilizzare una funzione con istruzione anziché un'espressione della funzione per le ragioni seguenti:

  • Le funzioni con istruzione sono più concise e più facili da leggere.

  • Le funzioni con istruzione consentono di utilizzare le parole chiave override e final.

  • Le istruzioni della funzione consentono di creare un legame più solido tra l'identificatore (il nome della funzione) e il codice, all'interno del corpo del metodo. Poiché il valore di una variabile può essere modificato mediante un'istruzione di assegnazione, il legame tra la variabile e la relativa espressione della funzione può essere sciolto in qualsiasi momento. Nonostante sia possibile ovviare a questo problema dichiarando la variabile con la parola chiave const anziché var, tale sistema non è consigliato, in quanto rende il codice di difficile lettura e impedisce l'uso delle parole chiave override e final.

Un caso in cui è consigliabile l'uso di un'espressione della funzione è quando si decide di associare una funzione all'oggetto prototype.

Metodi delle funzioni di costruzione

I metodi delle funzioni di costruzione, talvolta dette funzioni di costruzione, sono funzioni che condividono lo stesso nome della classe nella quale vengono definite. Qualsiasi codice incluso in un metodo di funzione di costruzione viene eseguito ogni volta che viene creata un'istanza della classe con la parola chiave new. Ad esempio, il codice seguente definisce una semplice classe chiamata Example, contenente un'unica proprietà denominata status. Il valore iniziale della variabile status viene definito all'interno della funzione di costruzione.

class Example 
{ 
    public var status:String; 
    public function Example() 
    { 
        status = "initialized"; 
    } 
} 
 
var myExample:Example = new Example(); 
trace(myExample.status); // output: initialized

I metodi delle funzioni di costruzione possono essere solo pubblici, tuttavia, l'impiego dell'attributo public è facoltativo. Nelle funzioni di costruzione non è possibile usare nessuno degli altri specificatori del controllo di accesso, incluso private, protected o internal. Con i metodi delle funzioni di costruzione non è inoltre possibile utilizzare spazi dei nomi definiti dall'utente.

Una funzione di costruzione può effettuare una chiamata esplicita alla funzione di costruzione della sua superclasse diretta mediante l'istruzione super(). Se la funzione di costruzione della superclasse non viene esplicitamente chiamata, il compilatore inserisce automaticamente una chiamata prima della prima istruzione nel corpo della funzione di costruzione. Per chiamare i metodi della superclasse, potete inoltre utilizzare il prefisso super come riferimento alla superclasse. Se decidete di utilizzare sia super() che super nello stesso corpo della funzione di costruzione, assicuratevi di chiamare prima super(). In caso contrario, il riferimento super non funziona correttamente. La funzione di costruzione super() deve inoltre essere chiamata prima di eventuali istruzioni throw o return.

Nell'esempio che segue è illustrato cosa accade se si tenta di utilizzare il riferimento super prima di chiamare la funzione di costruzione super(). Una nuova classe, ExampleEx, estende la classe Example. La funzione di costruzione ExampleEx tenta di accedere alla variabile status definita all'interno della sua superclasse, ma lo fa prima di chiamare super(). L'istruzione trace() che si trova all'interno della funzione di costruzione ExampleEx genera il valore null, in quanto la variabile status non risulta disponibile fino all'esecuzione della funzione di costruzione super().

class ExampleEx extends Example 
{ 
    public function ExampleEx() 
    { 
        trace(super.status); 
        super(); 
    } 
} 
 
var mySample:ExampleEx = new ExampleEx(); // output: null

Nonostante sia possibile utilizzare l'istruzione return all'interno di una funzione di costruzione, non è consentito che venga restituito un valore. In altre parole, le istruzioni return non devono avere espressioni o valori associati. Di conseguenza, i metodi delle funzioni di costruzione non possono restituire valori, ovvero non è possibile specificare tipi restituiti.

Se non si definisce un metodo di funzione di costruzione nella classe, il compilatore crea automaticamente una funzione di costruzione vuota. Se la classe viene estesa a un'altra classe, il compilatore include una chiamata super() nella funzione di costruzione generata.

Metodi statici

I metodi statici, chiamati anche metodi di classe, sono metodi che vengono dichiarati con la parola chiave static. I metodi statici, generalmente associati a una classe anziché all'istanza di una classe, sono utili per incorporare funzionalità relative a qualcosa di diverso dallo stato di singole istanze. Poiché i metodi statici vengono associati a un'intera classe, è possibile accedervi solo attraverso la classe stessa e non attraverso un'istanza della classe.

I metodi statici sono utili per incorporare funzioni che non si limitano a modificare lo stato delle istanze di classe. In altre parole, un metodo si definisce statico se fornisce funzionalità che non intervengono direttamente sul valore di un'istanza di classe. Ad esempio, la classe Date presenta un metodo statico denominato parse() che converte una stringa in un numero. Tale metodo è statico in quanto non modifica una singola istanza della classe. Il metodo parse() prende invece una stringa che rappresenta un valore data, l'analizza e restituisce un numero in un formato compatibile con la rappresentazione interna dell'oggetto Date. Questo metodo non è un metodo di istanza, in quanto non avrebbe senso applicarlo a un'istanza della classe Date.

Il metodo statico parse() è in contrasto con i metodi di istanza della classe Date, quale getMonth(). Il metodo getMonth() è un metodo di istanza, in quanto opera direttamente sul valore recuperando un componente specifico, il mese, di un'istanza Date.

Poiché i metodi statici non sono associati a singole istanze, non è possibile utilizzare le parole chiave this o super all'interno del corpo di un metodo statico. Sia il riferimento this che super hanno significato solo nel contesto di un metodo di istanza.

Diversamente da quanto accade in altri linguaggi di programmazione basati sulle classi, i metodi statici in ActionScript 3.0 non vengono ereditati.

Metodi di istanza

I metodi di istanza sono metodi dichiarati senza la parola chiave static. Questi metodi, che vengono associati alle istanze di una classe anziché all'intera classe, sono utili per implementare funzionalità che riguardano singole istanze di una classe. Ad esempio, la classe Array contiene un metodo di istanza denominato sort() che opera direttamente sulle istanze Array.

Nel corpo di un metodo di istanza, sono valide sia le variabili statiche che di istanza, il che significa che è possibile fare riferimento alle variabili definite all'interno della stessa classe mediante un semplice identificatore. Ad esempio, la classe CustomArray seguente estende la classe Array. La classe CustomArray definisce una variabile statica denominata arrayCountTotal che registra il numero totale di istanze della classe, una variabile di istanza denominata arrayNumber che registra l'ordine in cui le istanze sono state create e un metodo di istanza denominato getPosition() che restituisce i valori di tali variabili.

public class CustomArray extends Array 
{ 
    public static var arrayCountTotal:int = 0; 
    public var arrayNumber:int; 
 
    public function CustomArray() 
    { 
        arrayNumber = ++arrayCountTotal; 
    } 
     
    public function getArrayPosition():String 
    { 
         return ("Array " + arrayNumber + " of " + arrayCountTotal); 
    } 
}

Se il codice esterno alla classe deve accedere alla variabile statica arrayCountTotal mediante l'oggetto di classe, utilizzando CustomArray.arrayCountTotal, il codice che risiede nel corpo del metodo getPosition() può fare riferimento direttamente alla variabile statica arrayCountTotal. Ciò vale anche per le variabili statiche contenute nelle superclassi. Anche se le proprietà statiche non vengono ereditate in ActionScript 3.0, quelle presenti nelle superclassi sono nell'area di validità. Ad esempio, la classe Array presenta poche variabili statiche, una delle quali è una costante denominata DESCENDING. Il codice residente in una delle sottoclassi di Array può accedere alla costante statica DESCENDING mediante un semplice identificatore.

public class CustomArray extends Array 
{ 
    public function testStatic():void 
    { 
        trace(DESCENDING); // output: 2 
    } 
}

Il valore del riferimento this nel corpo di un metodo di istanza è un riferimento all'istanza alla quale il metodo è associato. Il codice seguente illustra come il riferimento this punti all'istanza contenente il metodo:

class ThisTest 
{ 
    function thisValue():ThisTest 
    { 
        return this; 
    } 
} 
 
var myTest:ThisTest = new ThisTest(); 
trace(myTest.thisValue() == myTest); // output: true

L'ereditarietà dei metodi di istanza può essere controllata con le parole chiave override e final. Utilizzate l'attributo override per ridefinire un metodo ereditato e l'attributo final per impedire alle sottoclassi di sostituire un metodo.

Metodi supplementari get e set

Le funzioni get e set, chiamate anche getter e setter, consentono di rispettare i principi di programmazione dell'information hiding e dell'incapsulamento, fornendo un'interfaccia di programmazione facile da usare per le classi create. Le funzioni get e set permettono di mantenere le proprietà della classe private all'interno della classe stessa, pur consentendo agli utenti della classe di accedere a tali proprietà come se stessero accedendo a una variabile di classe anziché chiamare un metodo di classe.

Il vantaggio di questo tipo di approccio è che consente di non utilizzare le funzioni accessor tradizionali con nomi poco pratici, quali getPropertyName() e setPropertyName(). Un altro vantaggio delle funzioni getter e setter è che evitano di gestire due funzioni pubbliche per ciascuna proprietà che consente l'accesso sia di lettura che di scrittura.

Nell'esempio seguente, la classe GetSet include le funzioni accessor get e set denominate publicAccess() che consentono l'accesso alla variabile privata denominata privateProperty:

class GetSet 
{ 
    private var privateProperty:String; 
     
    public function get publicAccess():String 
    { 
        return privateProperty; 
    } 
     
    public function set publicAccess(setValue:String):void 
    { 
        privateProperty = setValue; 
    } 
}

Se tentate di accedere alla proprietà privateProperty direttamente, si verifica l'errore seguente:

var myGetSet:GetSet = new GetSet(); 
trace(myGetSet.privateProperty); // error occurs

Gli utenti della classe GetSet utilizzano invece qualcosa che appare come una proprietà denominata publicAccess, ma che in realtà è una coppia di funzioni get e set che operano sulla proprietà privata chiamata privateProperty. Nell'esempio seguente viene creata un'istanza della classe GetSet, quindi viene impostato il valore di privateProperty mediante l'accessor pubblico denominato publicAccess:

var myGetSet:GetSet = new GetSet(); 
trace(myGetSet.publicAccess); // output: null 
myGetSet.publicAccess = "hello"; 
trace(myGetSet.publicAccess); // output: hello

Le funzioni getter e setter consentono inoltre di sostituire le proprietà ereditate da una superclasse, cosa non possibile se si utilizzano normali variabili membro di classe. Le variabili membro di classe dichiarate con la parola chiave var non possono essere sostituite in una sottoclasse. Le proprietà create con le funzioni getter e setter invece non presentano questo limite. È possibile utilizzare l'attributo override sulle funzioni getter e setter ereditate da una superclasse.

Metodi vincolati

Un metodo vincolato, o chiusura di un metodo, è semplicemente un metodo estratto dalla propria istanza. Tra gli esempi di metodi vincolati vi sono metodi passati come argomenti a una funzione o restituiti come valori da una funzione. Tra le novità di ActionScript 3.0 vi è un metodo vincolato simile a una chiusura di funzione, in quanto in grado di conservare il proprio ambiente lessicale anche se estratto dall'istanza a cui è associato. Tuttavia, la principale differenza tra un metodo vincolato e una chiusura di funzione è che il riferimento this del metodo vincolato resta collegato, o vincolato, all'istanza che implementa il metodo. In altre parole, il riferimento this in un metodo vincolato punta sempre all'oggetto originale che ha implementato il metodo. Nelle funzioni di chiusura, il riferimento this è generico, vale a dire che punta a qualsiasi oggetto associato alla funzione nel momento in cui viene chiamato.

Una corretta comprensione dei metodi vincolati è importante se si utilizza la parola chiave this. Tenete presente che la parola chiave this fornisce un riferimento a un oggetto principale del metodo. Per la maggior parte dei programmatori ActionScript la parola chiave this rappresenta sempre l'oggetto o la classe che contiene la definizione di un metodo. Senza i metodi vincolati, tuttavia, ciò non sarebbe sempre possibile. Nelle versioni precedenti di ActionScript, ad esempio, il riferimento this non era sempre riferito all'istanza che aveva implementato il metodo. Se in ActionScript 2.0 i metodi vengono estratti da un'istanza, non solo il riferimento this resta vincolato all'istanza originale, ma le variabili di membro e i metodi della classe dell'istanza non risultano disponibili. Il problema non esiste in ActionScript 3.0, in quanto i metodi vincolati vengono automaticamente creati quando un metodo viene passato come parametro. I metodi vincolati garantiscono che la parola chiave this faccia sempre riferimento all'oggetto o alla classe nella quale il metodo viene definito.

Il codice seguente definisce una classe denominata ThisTest, contenente un metodo chiamato foo() che definisce a sua volta il metodo vincolato e un metodo bar() che restituisce il metodo vincolato. Il codice esterno alla classe crea un'istanza della classe ThisTest, chiama il metodo bar() e memorizza il valore restituito in una variabile denominata myFunc.

class ThisTest 
{ 
    private var num:Number = 3; 
    function foo():void // bound method defined 
    { 
        trace("foo's this: " + this); 
        trace("num: " + num); 
    } 
    function bar():Function 
    { 
        return foo; // bound method returned 
    } 
} 
 
var myTest:ThisTest = new ThisTest(); 
var myFunc:Function = myTest.bar(); 
trace(this); // output: [object global] 
myFunc(); 
/* output:  
foo's this: [object ThisTest] 
output: num: 3 */

Le ultime due righe del codice mostrano che il riferimento this del metodo vincolato foo() continua a puntare a un'istanza della classe ThisTest, anche se il riferimento this che si trova nella linea precedente punta all'oggetto global. Inoltre, il metodo vincolato memorizzato nella variabile myFunc può ancora accedere alle variabili di membro della classe ThisTest. Se lo stesso codice viene eseguito in ActionScript 2.0, il riferimento this corrisponderebbe e la variabile num risulterebbe undefined.

Un'area in cui l'inserimento dei metodi vincolati è più evidente è quella dei gestori di eventi, in quanto il metodo addEventListener() richiede il passaggio di una funzione o di un metodo come argomento.

Enumerazioni con classi

Le enumerazioni sono tipi di dati personalizzati creati per incapsulare un piccolo gruppo di valori. ActionScript 3.0 non supporta una funzionalità di enumerazione specifica, a differenza di C++, che presenta la parola chiave enum, o di Java, che ha un'interfaccia di enumerazione propria. È tuttavia possibile creare enumerazioni mediante le classi e le costanti statiche. Ad esempio, la classe PrintJob in ActionScript 3.0 impiega un'enumerazione denominata PrintJobOrientation per memorizzare i valori "landscape" e "portrait", come illustrato nel codice seguente:

public final class PrintJobOrientation 
{ 
    public static const LANDSCAPE:String = "landscape"; 
    public static const PORTRAIT:String = "portrait"; 
}

Per convenzione, una classe di enumerazione viene dichiarata con l'attributo final in quanto non vi è necessità di estendere la classe. La classe include solo membri statici, di conseguenza non si potranno creare istanze della classe. Al contrario, è possibile accedere ai valori di enumerazione direttamente tramite l'oggetto di classe, come illustrato nel seguente estratto di codice:

var pj:PrintJob = new PrintJob(); 
if(pj.start()) 
{ 
    if (pj.orientation == PrintJobOrientation.PORTRAIT) 
    { 
        ... 
    } 
    ... 
}

Tutte le classi di enumerazione in ActionScript 3.0 contengono solo variabili di tipo String, int o uint. Il vantaggio di utilizzare enumerazioni anziché stringhe di caratteri o valori numerici è che gli errori tipografici sono più facilmente rilevabili nelle enumerazioni. Se digitate in modo errato il nome di un'enumerazione, il compilatore di ActionScript genera un errore. Se usate valori letterali, il compilatore non rileva gli errori ortografici o l'uso di un numero errato. Nell'esempio precedente, se il nome della costante di enumerazione non è corretto, il compilatore genera un errore, come illustrato nell'estratto seguente:

    if (pj.orientation == PrintJobOrientation.PORTRAI) // compiler error

Tuttavia, il compilatore non genera un errore se la stringa di caratteri digitata contiene un errore ortografico, come nel caso seguente:

    if (pj.orientation == "portrai") // no compiler error

Una seconda tecnica per la creazione di enumerazioni prevede anch'essa la creazione di una classe separata con proprietà statiche per l'enumerazione. Ciò che differenzia questa tecnica, tuttavia, è che le proprietà statiche contengono un'istanza della classe anziché una stringa o un valore intero. Ad esempio, il seguente codice consente di creare una classe di enumerazione per i giorni della settimana:

public final class Day 
{ 
    public static const MONDAY:Day = new Day(); 
    public static const TUESDAY:Day = new Day(); 
    public static const WEDNESDAY:Day = new Day(); 
    public static const THURSDAY:Day = new Day(); 
    public static const FRIDAY:Day = new Day(); 
    public static const SATURDAY:Day = new Day(); 
    public static const SUNDAY:Day = new Day(); 
}

Questa tecnica non viene utilizzata da ActionScript 3.0, ma è impiegata da numerosi sviluppatori che ne apprezzano in particolare la funzionalità di verifica tipi ottimizzata. Ad esempio, un metodo in grado di restituire un valore di enumerazione può limitare il valore restituito al tipo di dati dell'enumerazione. Il codice seguente mostra una funzione in grado di restituire non solo un giorno della settimana, ma anche una chiamata a una funzione che impiega il tipo dell'enumerazione come annotazione di tipo:

function getDay():Day 
{ 
    var date:Date = new Date(); 
    var retDay:Day; 
    switch (date.day) 
    { 
        case 0: 
            retDay = Day.MONDAY; 
            break; 
        case 1: 
            retDay = Day.TUESDAY; 
            break; 
        case 2: 
            retDay = Day.WEDNESDAY; 
            break; 
        case 3: 
            retDay = Day.THURSDAY; 
            break; 
        case 4: 
            retDay = Day.FRIDAY; 
            break; 
        case 5: 
            retDay = Day.SATURDAY; 
            break; 
        case 6: 
            retDay = Day.SUNDAY; 
            break; 
    } 
    return retDay; 
} 
 
var dayOfWeek:Day = getDay();

È inoltre possibile ottimizzare la classe Day in modo che a ogni giorno della settimana venga associato un numero intero e fornire un metodo toString() che restituisca una rappresentazione del giorno sotto forma di stringa.

Classi delle risorse incorporate

In ActionScript 3.0 vengono impiegate classi speciali, chiamate classi delle risorse incorporate, per rappresentare risorse incorporate. Una risorsa incorporata è una risorsa, quale un suono, un'immagine o un carattere, che viene inclusa in un file SWF in fase di compilazione. L'incorporamento, anziché il caricamento dinamico, di una risorsa ne garantisce la disponibilità in fase di runtime, ma al costo di un incremento delle dimensioni del file SWF.

Uso delle classi delle risorse incorporate in Flash Professional

Per incorporare una risorsa, in primo luogo inseritela nella libreria di un file FLA. In secondo luogo, utilizzate la finestra di dialogo Proprietà del concatenamento della risorsa per specificare il nome della classe della risorsa incorporata. Se una classe con questo nome non esiste nel percorso di classe, ne viene generata una automaticamente. A questo punto, potete creare un'istanza della classe della risorsa incorporata e utilizzare qualsiasi proprietà e metodo definito o ereditato dalla classe. Ad esempio, il codice seguente può essere utilizzato per riprodurre l'audio incorporato collegato alla classe di una risorsa incorporata di nome PianoMusic:

var piano:PianoMusic = new PianoMusic(); 
var sndChannel:SoundChannel = piano.play();

In alternativa, potete utilizzare il tag per metadati [Embed] per incorporare risorse in un progetto Flash Professional, come descritto di seguito. Se utilizzate il tag per metadati [Embed] nel codice, Flash Professional utilizza il compilatore Flex, anziché il compilatore Flash Professional, per compilare il progetto.

Uso delle classi delle risorse incorporate mediante il compilatore Flex

Se compilate il codice utilizzando il compilatore Flex, per incorporare una risorsa nel codice ActionScript utilizzate il tag per metadati [Embed]. Inserite la risorsa nella cartella di origine principale o in un'altra cartella del percorso di compilazione del progetto. Quando rileva il tag per metadati Embed, il compilatore di Adobe Flex crea automaticamente la classe della risorsa incorporata. Potete accedere alla classe usando una variabile con tipo di dati Class dichiarata subito dopo il tag per metadati [Embed]. Ad esempio il codice seguente incorpora un file audio denominato sound1.mp3 e usa una variabile denominata soundCls per memorizzare un riferimento alla classe della risorsa incorporata associata al file audio. Nell'esempio viene poi creata un'istanza della classe della risorsa incorporata e viene chiamato il metodo play() per quella istanza:

package 
{ 
    import flash.display.Sprite; 
    import flash.media.SoundChannel; 
    import mx.core.SoundAsset; 
 
    public class SoundAssetExample extends Sprite 
    { 
        [Embed(source="sound1.mp3")] 
        public var soundCls:Class; 
         
        public function SoundAssetExample() 
        { 
            var mySound:SoundAsset = new soundCls() as SoundAsset; 
            var sndChannel:SoundChannel = mySound.play(); 
        } 
    } 
}

Adobe Flash Builder

Per utilizzare il tag per metadati [Embed] in un progetto ActionScript di Flash Builder, importate tutte le classi richieste dal framework Flex. Per incorporare i suoni, ad esempio, importate la classe mx.core.SoundAsset. Per usare il framework Flex, inserite il file framework.swc nel percorso di compilazione di ActionScript. In questo modo le dimensioni del file SWF aumentano.

Adobe Flex

In alternativa, in Flex potete incorporare una risorsa usando la direttiva @Embed() in una definizione del tag MXML.