Pacchetti e spazi dei nomi

Pacchetti e spazi dei nomi sono concetti correlati. I pacchetti consentono di “impacchettare” insieme le definizioni di classe in modo da facilitare la condivisione del codice e ridurre al minimo i conflitti tra nomi. Gli spazi dei nomi permettono di controllare la visibilità degli identificatori, quali i nomi di proprietà e di metodi, e possono essere applicati al codice sia all'interno che all'esterno di un pacchetto. I pacchetti consentono di organizzare i file di classe e gli spazi dei nomi di gestire la visibilità di singole proprietà e metodi.

Pacchetti

In ActionScript 3.0, i pacchetti sono implementati insieme agli spazi dei nomi, ma non sono la stessa cosa. Quando dichiarate un pacchetto, implicitamente create un tipo speciale di spazio dei nomi con la garanzia che sarà noto in fase di compilazione. Al contrario, uno spazio dei nomi creato esplicitamente non è necessariamente noto in fase di compilazione.

Nell'esempio seguente viene utilizzata la direttiva package per creare un pacchetto semplice che contiene un'unica classe:

package samples 
{ 
    public class SampleCode 
    { 
        public var sampleGreeting:String; 
        public function sampleFunction() 
        { 
            trace(sampleGreeting + " from sampleFunction()"); 
        } 
    } 
}

Il nome della classe di questo esempio è SampleCode. Poiché la classe è all'interno del pacchetto samples, il compilatore qualifica automaticamente il nome della classe in fase di compilazione con il rispettivo nome completo: samples.SampleCode. Il compilatore qualifica anche i nomi di qualsiasi proprietà o metodo, in modo che sampleGreeting e sampleFunction() diventino rispettivamente samples.SampleCode.sampleGreeting e samples.SampleCode.sampleFunction().

Molti sviluppatori, specialmente quelli con esperienza Java, potrebbero scegliere di collocare solo le classi al livello principale di un pacchetto. Tuttavia, ActionScript 3.0 supporta non solo le classi in tale posizione, ma anche le variabili, le funzioni e persino le istruzioni. Uno degli usi avanzati di questa caratteristica consiste nel definire uno spazio dei nomi al livello principale di un pacchetto, in modo che sia disponibile a tutte le classi del pacchetto. Notate, tuttavia, che soltanto due specificatori di accesso (public e internal) sono consentiti al livello principale di un pacchetto. A differenza di Java, che consente di dichiarare come private le classi nidificate, ActionScript 3.0 non supporta classi nidificate o private.

Per molti altri aspetti, tuttavia, i pacchetti di ActionScript 3.0 sono simili a quelli del linguaggio di programmazione Java. Come potete notare nell'esempio precedente, i riferimenti ai nomi completi dei pacchetti vengono espressi utilizzando l'operatore punto (.), proprio come in Java. Potete sfruttare i pacchetti per organizzare il codice in una struttura gerarchica intuitiva che possa essere utilizzata da altri programmatori. In questo modo si facilita la condivisione del codice, poiché si possono creare pacchetti personalizzati da mettere a disposizione degli altri e utilizzare nel proprio codice pacchetti creati da altri programmatori.

Inoltre, l'uso dei pacchetti fa sì che i nomi di identificazione utilizzati siano univoci e non in conflitto con quelli di altri pacchetti. Si potrebbe addirittura sostenere che questo sia il vantaggio principale dei pacchetti. Ad esempio, supponete che due programmatori abbiano deciso di condividere il loro codice e che ciascuno dei due abbia creato una classe chiamata SampleCode. Senza i pacchetti si creerebbe un conflitto tra i nomi e l'unica soluzione sarebbe quella di rinominare una delle due classi. Grazie ai pacchetti, invece, il conflitto viene evitato facilmente collocando una o (preferibilmente) entrambe le classi in pacchetti con nomi univoci.

È anche possibile includere dei punti (.) incorporati in un pacchetto per creare pacchetti nidificati, allo scopo di realizzare un'organizzazione gerarchica dei pacchetti. Un ottimo esempio è il pacchetto flash.display fornito da ActionScript 3.0 e nidificato all'intero del pacchetto flash.

La maggior parte di ActionScript 3.0 è organizzato sotto il pacchetto flash. Ad esempio, il pacchetto flash.display contiene l'API dell'elenco di visualizzazione e il pacchetto flash.events contiene il nuovo modello di eventi.

Creazione di pacchetti

ActionScript 3.0 offre una notevole flessibilità nell'organizzazione di pacchetti, classi e file di origine. Le versioni precedenti di ActionScript consentivano l'uso di un'unica classe per ogni file di origine e imponevano la corrispondenza tra il nome del file di origine e quello della classe. ActionScript 3.0 invece permette di includere più classi nello stesso file di origine, ma una sola classe di ogni file può essere resa disponibile al codice esterno al file stesso. In altre parole, solo una classe di ogni file può essere dichiarata all'interno di una dichiarazione di pacchetto. Le eventuali altre classi devono essere dichiarate all'esterno, pertanto risultano invisibili al codice esterno al file di origine. Il nome della classe dichiarata nella definizione del pacchetto deve corrispondere al nome del file di origine.

La maggiore flessibilità di ActionScript 3.0 si può notare anche nel modo in cui vengono definiti i pacchetti. Nelle versioni precedenti di ActionScript, i pacchetti rappresentavano semplicemente directory in cui inserire i file di origine; inoltre, i pacchetti non venivano dichiarati con l'istruzione package, ma piuttosto il nome del pacchetto veniva incluso come parte del nome completo della classe nella dichiarazione della classe. In ActionScript 3.0 i pacchetti rappresentano ancora delle directory, ma il loro contenuto non è limitato alle classi. L'istruzione package di ActionScript 3.0 consente di dichiarare non solo un pacchetto ma anche variabili, funzioni e spazi dei nomi al livello principale di un pacchetto. È anche possibile includere istruzioni eseguibili, sempre al livello principale del pacchetto. Se scegliete di dichiarare variabili, funzioni o spazi dei nomi al livello principale di un pacchetto, gli unici attributi disponibili a quel livello sono public e internal e soltanto una dichiarazione a livello di pacchetto per ciascun file può utilizzare l'attributo public, a prescindere che venga dichiarata una classe, una variabile, una funzione o uno spazio dei nomi.

I pacchetti sono utili per organizzare il codice e per evitare conflitti tra i nomi. Il concetto di pacchetto non va confuso con quello di ereditarietà delle classi, al quale non è correlato. Due classi che risiedono nello stesso pacchetto hanno uno spazio dei nomi in comune, ma non sono necessariamente correlate tra loro in alcun altro modo. Analogamente, un pacchetto nidificato potrebbe non avere alcune relazione semantica con il pacchetto di livello superiore.

Importazione dei pacchetti

Per utilizzare una classe che si trova all'interno di un pacchetto, dovete importare il pacchetto stesso o la classe specifica. In ActionScript 2.0, invece, l'importazione delle classi era opzionale.

Ad esempio, considerate l'esempio di classe SampleCode presentato in precedenza. Se la classe risiede in un pacchetto chiamato samples, dovete utilizzare una delle seguenti istruzioni import per utilizzare la classe SampleCode:

import samples.*;

oppure

import samples.SampleCode;

In generale, le istruzioni import devono essere il più possibile specifiche. Se prevedete di utilizzare solo la classe SampleCode del pacchetto samples, dovete importare solo la classe SampleCode anziché l'intero pacchetto al quale appartiene. L'importazione di interi pacchetti può determinare conflitti imprevisti tra i nomi.

Inoltre, dovete collocare il codice che definisce il pacchetto o la classe all'interno del percorso di classe. Il percorso di classe (classpath) è un elenco definito dall'utente dei percorsi di directory locali, che determina dove il compilatore cerca i pacchetti e le classi importate. Talvolta il percorso di classe viene anche definito percorso di compilazione (build path) o percorso di origine (source path).

Dopo aver importato correttamente la classe o il pacchetto, potete utilizzare il nome completo della classe (samples.SampleCode) oppure semplicemente il nome della classe (SampleCode).

I nomi completi sono utili quando classi, metodi o proprietà con nomi identici possono creare ambiguità nel codice, ma possono risultare più difficili da gestire se utilizzati per tutti gli identificatori. Ad esempio, l'uso del nome completo determina un codice troppo verboso quando si crea un'istanza della classe SampleCode:

var mySample:samples.SampleCode = new samples.SampleCode();

Man mano che aumentano i livelli di nidificazione dei pacchetti, diminuisce la leggibilità del codice. Nei casi in cui siete sicuri che la presenza di identificatori ambigui non rappresenta un problema, l'uso degli identificatori semplici consente di ottenere codice più leggibile. Ad esempio, il codice che crea un'istanza della classe SampleCode è molto più semplice se si include solo l'identificatore di classe:

var mySample:SampleCode = new SampleCode();

Se tentate di utilizzare nomi di identificatori senza aver prima importato il pacchetto o la classe corrispondente, il compilatore non è in grado di trovare le definizioni di classe. D'altro canto, tuttavia, se importate un pacchetto o una classe e tentate di definire un nome che è in conflitto con un nome importato, viene generato un errore.

Quando si crea un pacchetto, lo specificatore di accesso predefinito per tutti i membri del pacchetto è internal, vale a dire che, per impostazione predefinita, tutti i membri del pacchetto sono visibili soltanto agli altri membri dello stesso pacchetto. Se desiderate che una classe sia disponibile al codice esterno al pacchetto, dovete dichiararla come public. Ad esempio, il pacchetto seguente contiene due classi, SampleCode e CodeFormatter:

// SampleCode.as file 
package samples 
{ 
    public class SampleCode {} 
} 
 
// CodeFormatter.as file 
package samples 
{ 
    class CodeFormatter {} 
}

La classe SampleCode è visibile all'esterno del pacchetto perché è dichiarata come una classe public. La classe CodeFormatter, al contrario, è visibile solo nel pacchetto samples. Se tentate di accedere alla classe CodeFormatter esternamente al pacchetto samples, viene generato un errore, come mostrato nell'esempio seguente:

import samples.SampleCode; 
import samples.CodeFormatter; 
var mySample:SampleCode = new SampleCode(); // okay, public class 
var myFormatter:CodeFormatter = new CodeFormatter(); // error

Se desiderate che ambedue le classi siano disponibili al codice esterno al pacchetto, dovete dichiararle entrambe come public. Non è possibile applicare l'attributo public alla dichiarazione del pacchetto.

I nomi completi sono utili per risolvere conflitti tra nomi che potrebbero verificarsi quando si usano i pacchetti. Uno scenario di questo tipo si potrebbe presentare se si importano due pacchetti che definiscono classi con lo stesso identificatore. Ad esempio, esaminate il pacchetto seguente, che contiene a sua volta una classe chiamata SampleCode:

package langref.samples 
{ 
    public class SampleCode {} 
}

Se importate entrambe le classi, come nell'esempio seguente, si determina un conflitto di nomi quando utilizzate la classe SampleCode:

import samples.SampleCode; 
import langref.samples.SampleCode; 
var mySample:SampleCode = new SampleCode(); // name conflict

Il compilatore non ha modo di sapere quale classe SampleCode deve essere utilizzata. Per risolvere il conflitto, dovete utilizzare il nome completo di ciascuna classe, come indicato di seguito:

var sample1:samples.SampleCode = new samples.SampleCode(); 
var sample2:langref.samples.SampleCode = new langref.samples.SampleCode();
Nota: i programmatori con esperienza in C++ spesso confondono l'istruzione import con #include. La direttiva #include è necessaria in C++ perché i compilatori C++ elaborano un file alla volta e non cercano le definizioni di classe in altri file a meno che non venga incluso esplicitamente un file di intestazione. Anche in ActionScript 3.0 è presente una direttiva include, che tuttavia non è progettata per l'importazione di classi e pacchetti. Per importare classi o pacchetti in ActionScript 3.0, dovete utilizzare l'istruzione import e inserire nel percorso di classe il file di origine che contiene il pacchetto.

Spazi dei nomi

Gli spazi dei nomi permettono di controllare la visibilità delle proprietà e dei metodi creati dal programmatore. Gli specificatori di controllo dell'accesso public, private, protected e internal possono essere considerati come spazi dei nomi incorporati. Se riscontrate che questi specificatori predefiniti non soddisfano tutte le vostre esigenze, potete creare spazi dei nomi personalizzati.

Se avete esperienza con gli spazi dei nomi XML, questo argomento vi risulterà già noto, benché la sintassi e i dettagli dell'implementazione ActionScript siano leggermente diversi rispetto al linguaggio XML. Se è la prima volta che utilizzate gli spazi dei nomi, il concetto in sé è di facile comprensione ma l'implementazione prevede una terminologia specifica che occorrerà apprendere.

Per comprendere il funzionamento degli spazi dei nomi, è utile sapere che il nome di una proprietà o metodo contiene sempre due parti: un identificatore e uno spazio dei nomi. L'identificatore può essere considerato equivalente a un nome. Ad esempio, gli identificatori nella definizione di classe seguente sono sampleGreeting e sampleFunction():

class SampleCode 
{ 
    var sampleGreeting:String; 
    function sampleFunction () { 
        trace(sampleGreeting + " from sampleFunction()"); 
    } 
}

Ogni qual volta le definizioni non sono precedute da un attributo spazio dei nomi, i loro nomi sono qualificati dallo spazio dei nomi internal predefinito, il che significa che sono visibili solo a chiamanti nello stesso pacchetto. Se è impostata la modalità rigorosa, il compilatore genera un'avvertenza per segnalare che lo spazio dei nomi internal viene applicato a tutti gli identificatori privi di attributo namespace. Per far sì che un identificatore sia disponibile senza limiti, dovete anteporre esplicitamente al suo nome l'attributo public. Nel codice di esempio precedente, sampleGreeting e sampleFunction() hanno un valore spazio dei nomi di internal.

L'utilizzo degli spazi dei nomi prevede tre passaggi fondamentali. Innanzi tutto, dovete definire lo spazio dei nomi mediante la parola chiave namespace. Ad esempio, il codice seguente definisce lo spazio dei nomi version1:

namespace version1;

In secondo luogo, applicate lo spazio dei nomi utilizzandolo al posto di uno specificatore di accesso in una proprietà o nella dichiarazione di un metodo. L'esempio seguente inserisce una funzione denominata myFunction() nello spazio dei nomi version1:

version1 function myFunction() {}

Terzo, dopo che è stato applicato, potete fare riferimento allo spazio dei nomi con la direttiva use o qualificando il nome di un identificatore con uno spazio dei nomi. L'esempio seguente fa riferimento alla funzione myFunction() mediante la direttiva use:

use namespace version1; 
myFunction();

Potete anche utilizzare un nome qualificato per fare riferimento alla funzione myFunction(), come mostrato nell'esempio seguente:

version1::myFunction();

Definizione degli spazi dei nomi

Gli spazi dei nomi contengono un solo valore, l'URI (Uniform Resource Identifier), che talvolta viene definito nome dello spazio dei nomi. Un URI consente di rendere univoca la definizione di uno spazio dei nomi.

Per creare uno spazio dei nomi, occorre dichiarare una definizione namespace. Quest'ultima può contenere un URI esplicito (come per gli spazi dei nomi XML) oppure esserne priva. L'esempio seguente mostra uno spazio dei nomi definito con un URI:

namespace flash_proxy = "http://www.adobe.com/flash/proxy";

L'URI funge da stringa di identificazione univoca per lo spazio dei nomi. Se viene omesso, come nell'esempio seguente, il compilatore crea al suo posto una stringa di identificazione univoca interna, alla quale non è possibile accedere.

namespace flash_proxy;

Una volta definito uno spazio dei nomi, con o senza URI, non è possibile ridefinirlo all'interno della stessa area di validità. Un eventuale tentativo in questo senso produce un errore del compilatore.

Se uno spazio dei nomi viene definito all'interno di un pacchetto o di una classe, potrebbe non essere visibile per il codice esterno a tale pacchetto o classe, a meno che non venga utilizzato lo specificatore di controllo accesso appropriato. Ad esempio, nel codice seguente lo spazio dei nomi flash_proxy è definito all'interno del pacchetto flash.utils. Nell'esempio, l'assenza di uno specificatore di controllo accesso fa sì che lo spazio dei nomi flash_proxy sia visibile solo al codice che si trova nel pacchetto flash.utils e invisibile a tutto il codice esterno a tale pacchetto:

package flash.utils 
{ 
    namespace flash_proxy; 
}

Il codice seguente utilizza l'attributo public per rendere visibile lo spazio dei nomi flash_proxy a codice all'esterno del pacchetto:

package flash.utils 
{ 
    public namespace flash_proxy; 
}

Applicazione degli spazi dei nomi

Applicare uno spazio dei nomi significa inserire una definizione all'interno di uno spazio dei nomi. Le definizioni che possono essere inserite negli spazi dei nomi sono le funzioni, le variabili e le costanti (non è possibile inserire una classe in uno spazio dei nomi personalizzato).

Considerate, ad esempio, una funzione dichiarata mediante lo specificatore di controllo accesso public. L'uso dell'attributo public in una definizione di funzione determina l'inserimento della funzione nello spazio dei nomi pubblico e la conseguente disponibilità della funzione stessa per tutto il codice. Una volta definito uno spazio dei nomi personalizzato, potete utilizzarlo come l'attributo public, rendendo disponibile la definizione al codice che può fare riferimento allo spazio dei nomi. Ad esempio, se definite lo spazio dei nomi example1, potete aggiungere un metodo chiamato myFunction() usando example1 come attributo, come nell'esempio seguente:

namespace example1; 
class someClass 
{ 
    example1 myFunction() {} 
}

Se dichiarate il metodo myFunction() utilizzando lo spazio dei nomi example1 come un attributo, significa che il metodo appartiene allo spazio dei nomi example1.

Quando applicate uno spazio dei nomi, tenete presente quanto segue:

  • È possibile applicare un solo spazio dei nomi a ogni dichiarazione.

  • Non è possibile applicare un attributo namespace a più di una definizione alla volta. In altre parole, se volete applicare uno spazio dei nomi a dieci diverse funzioni, dovete aggiungere l'attributo namespace a ciascuna delle dieci definizioni di funzione.

  • Se applicate uno spazio dei nomi, non potete specificare anche uno specificatore di controllo accesso, poiché i due elementi si escludono a vicenda. In altre parole, non è possibile dichiarare una funzione o una proprietà con l'attributo public, private, protected o internal dopo aver già applicato lo spazio dei nomi corrispondente.

Riferimenti agli spazi dei nomi

Non occorre fare riferimento in modo esplicito a uno spazio dei nomi quando utilizzate un metodo o una proprietà dichiarata con uno degli specificatori di controllo accesso, quali public, private, protected e internal, dal momento che l'accesso a questi spazi dei nomi è controllato dal contesto. Ad esempio, le definizioni inserite nello spazio dei nomi private sono automaticamente disponibili al codice che si trova all'interno della stessa classe. Nel caso degli spazi dei nomi personalizzati, tuttavia, questa “sensibilità al contesto” non esiste. Per utilizzare un metodo o una proprietà inserita in uno spazio dei nomi personalizzato, dovete fare riferimento in modo esplicito allo spazio dei nomi.

È possibile fare riferimento agli spazi dei nomi mediante la direttiva use namespace oppure qualificando il nome con lo spazio dei nomi mediante la sintassi ::. Fare riferimento a uno spazio dei nomi con la direttiva use namespace consente di “aprire” lo spazio dei nomi, in modo che possa essere applicato a qualsiasi identificatore non qualificato. Ad esempio, se avete definito lo spazio dei nomi example1, potete accedere a nomi nello spazio dei nomi utilizzando use namespace example1:

use namespace example1; 
myFunction();

È possibile aprire più spazi dei nomi nello stesso momento. Quando utilizzate la direttiva use namespace, lo spazio dei nomi rimane aperto nell'intero blocco di codice in cui è stato aperto. Non esiste un modo per chiudere esplicitamente uno spazio dei nomi.

La presenza contemporanea di due o più spazi dei nomi aperti, tuttavia, aumenta la probabilità di conflitti tra nomi. Se preferite non aprire uno spazio dei nomi, potete evitare di usare la direttiva use namespace oppure qualificando il nome del metodo o della proprietà con lo spazio dei nomi e il segno ::. Ad esempio, nel codice seguente il nome myFunction() viene qualificato con lo spazio dei nomi example1:

example1::myFunction();

Uso degli spazi dei nomi

Nella classe flash.utils.Proxy di ActionScript 3.0 potete trovare un esempio di uno spazio dei nomi reale che viene utilizzato per evitare conflitti tra nomi. La classe Proxy, che sostituisce la proprietà Object.__resolve di ActionScript 2.0, permette di intercettare i riferimenti a proprietà o metodi non definiti prima che si verifichi un errore. Tutti i metodi della classe Proxy risiedono nello spazio dei nomi flash_proxy per impedire conflitti tra i nomi.

Per comprendere meglio come viene utilizzato lo spazio dei nomi flash_proxy, è necessario capire come funziona la classe Proxy. La funzionalità di questa classe è disponibile unicamente alle classi che ereditano da essa. In altre parole, se desiderate utilizzare i metodi della classe Proxy di un oggetto, la definizione di classe dell'oggetto deve estendere la classe Proxy. Ad esempio, se volete intercettare i tentativi di chiamare un metodo non definito, potete estendere la classe Proxy ed eseguire l'override del metodo callProperty() della stessa classe.

Si è detto in precedenza che l'implementazione degli spazi dei nomi è solitamente un processo che prevede tre passaggi: definire uno spazio dei nomi, applicarlo e farvi riferimento. Tuttavia, poiché non viene mai fatto riferimento in modo esplicito a nessuno dei metodi della classe Proxy, lo spazio dei nomi flash_proxy viene solo definito e applicato e non specificato in un riferimento. ActionScript 3.0 definisce lo spazio dei nomi flash_proxy e lo applica nella classe Proxy. Il vostro codice deve soltanto applicare lo spazio dei nomi flash_proxy alle classi che estendono la classe Proxy.

Lo spazio dei nomi flash_proxy è definito nel pacchetto flash.utils in un modo simile al seguente:

package flash.utils 
{ 
    public namespace flash_proxy; 
}

Lo spazio dei nomi viene applicato ai metodi della classe Proxy come indicato nel seguente codice estratto da tale classe:

public class Proxy 
{ 
    flash_proxy function callProperty(name:*, ... rest):* 
    flash_proxy function deleteProperty(name:*):Boolean 
    ... 
}

Come mostrato nel codice seguente, è necessario innanzitutto importare la classe Proxy e lo spazio dei nomi flash_proxy, quindi occorre dichiarare la classe in modo che estenda la classe Proxy (nonché aggiungere l'attributo dynamic, se il compilatore è in modalità rigorosa). Se sostituite il metodo callProperty(), dovete utilizzare lo spazio dei nomi flash_proxy.

package 
{ 
    import flash.utils.Proxy; 
    import flash.utils.flash_proxy; 
 
    dynamic class MyProxy extends Proxy 
    { 
        flash_proxy override function callProperty(name:*, ...rest):* 
        { 
            trace("method call intercepted: " + name); 
        } 
    } 
}

Se create un'istanza della classe MyProxy e chiamate un metodo non definito, ad esempio il metodo testing()chiamato nell'esempio che segue, l'oggetto Proxy intercetta la chiamata al metodo ed esegue le istruzioni contenute nel metodo callProperty()sostituito (in questo caso, una semplice istruzione trace()).

var mySample:MyProxy = new MyProxy(); 
mySample.testing(); // method call intercepted: testing

L'inclusione dei metodi della classe Proxy all'interno dello spazio dei nomi flash_proxy presenta due vantaggi. Innanzi tutto, la presenza di uno spazio dei nomi separato riduce la quantità di elementi nell'interfaccia pubblica di qualunque classe che estende la classe Proxy. (Vi sono circa una dozzina di metodi nella classe Proxy che possono essere sostituiti, nessuno dei quali è progettato per essere chiamato direttamente. Includerli tutti nello spazio dei nomi pubblico potrebbe creare confusione.) In secondo luogo, l'uso dello spazio dei nomi flash_proxy permette di evitare conflitti tra i nomi qualora la sottoclasse Proxy contenga nomi di metodi di istanze che corrispondono a nomi di metodi della classe Proxy. Ad esempio, supponete che uno dei metodi sia denominato callProperty(). Il codice seguente è valido perché la versione personalizzata del metodo callProperty() si trova in uno spazio dei nomi diverso:

dynamic class MyProxy extends Proxy 
{ 
    public function callProperty() {} 
    flash_proxy override function callProperty(name:*, ...rest):* 
    { 
        trace("method call intercepted: " + name); 
    } 
}

Gli spazi dei nomi sono utili anche quando desiderate fornire accesso a metodi e proprietà in un modo che non sarebbe possibile con i quattro specificatori di controllo accesso (public, private, internal e protected). Ad esempio, se avete vari metodi di utilità sparsi in diversi pacchetti e desiderate renderli disponibili a tutti i pacchetti senza tuttavia renderli pubblici, potete creare uno spazio dei nomi e utilizzarlo come specificatore di controllo accesso personalizzato.

L'esempio seguente utilizza uno spazio dei nomi definito dall'utente per raggruppare due funzioni che si trovano in pacchetti differenti. Grazie a questa operazione, potete rendere visibili entrambe le funzioni a una classe o a un pacchetto tramite una singola istruzione use namespace.

L'esempio che segue usa quattro file per dimostrare questa tecnica. Tutti i file devono trovarsi all'interno del percorso di classe. Il primo, myInternal.as, viene utilizzato per definire lo spazio dei nomi myInternal. Poiché si trova in un pacchetto denominato example, è necessario inserirlo in una cartella con lo stesso nome. Lo spazio dei nomi viene contrassegnato come public in modo che possa essere importato in altri pacchetti.

// myInternal.as in folder example 
package example 
{ 
    public namespace myInternal = "http://www.adobe.com/2006/actionscript/examples"; 
}

Il secondo e il terzo file, Utility.as e Helper.as, definiscono le classi che contengono i metodi da rendere disponibili agli altri pacchetti. Poiché la classe Utility è nel pacchetto example.alpha, il file deve essere inserito in una cartella denominata alpha a sua volta contenuta nella cartella example. Allo stesso modo, la classe Helper si trova nel pacchetto example.alpha e il file corrispondente deve essere inserito nella sottocartella beta della cartella example. Entrambi i pacchetti, example.alpha e example.beta, devono importare lo spazio dei nomi per poterlo utilizzare.

// Utility.as in the example/alpha folder 
package example.alpha 
{ 
    import example.myInternal; 
     
    public class Utility 
    { 
        private static var _taskCounter:int = 0; 
     
        public static function someTask() 
        { 
            _taskCounter++; 
        } 
         
        myInternal static function get taskCounter():int 
        { 
            return _taskCounter; 
        } 
    } 
} 
 
// Helper.as in the example/beta folder 
package example.beta 
{ 
    import example.myInternal; 
     
    public class Helper 
    { 
        private static var _timeStamp:Date; 
         
        public static function someTask() 
        { 
            _timeStamp = new Date(); 
        } 
         
        myInternal static function get lastCalled():Date 
        { 
            return _timeStamp; 
        } 
    } 
}

Il quarto file, NamespaceUseCase.as, è la classe principale dell'applicazione e deve essere allo stesso livello della cartella example. In Flash Professional questa classe verrebbe utilizzata come classe documento per il file FLA. Anche la classe NamespaceUseCase importa lo spazio dei nomi myInternal e lo utilizza per chiamare i due metodi statici contenuti negli altri pacchetti. L'esempio utilizza i metodi statici solo per semplificare il codice. Nello spazio dei nomi myInternal è possibile inserire sia metodi statici che di istanza.

// NamespaceUseCase.as 
package 
{ 
    import flash.display.MovieClip; 
    import example.myInternal; // import namespace 
    import example.alpha.Utility;// import Utility class 
    import example.beta.Helper;// import Helper class 
     
    public class NamespaceUseCase extends MovieClip 
    { 
        public function NamespaceUseCase() 
        { 
            use namespace myInternal; 
             
            Utility.someTask(); 
            Utility.someTask(); 
            trace(Utility.taskCounter); // 2 
             
            Helper.someTask(); 
            trace(Helper.lastCalled); // [time someTask() was last called] 
        } 
    } 
}