Paket och namnutrymmen

Paket och namnutrymmen är relaterade begrepp. Med paket kan du samla ihop klassdefinitioner på ett sätt som underlättar koddelning och som minimerar namnkonflikter. Med namnutrymmen kan du styra visningen av identifierare, till exempel egenskaps- och metodnamn, och de kan användas i kod vare sig de finns inuti eller utanför ett paket. Med paket kan du organisera klassfiler och med namnutrymmen kan du hantera visningen av individuella egenskaper och metoder.

Paket

Paket i ActionScript 3.0 implementeras med namnutrymmen, men är inte synonymer med dem. När du deklarerar ett paket skapar du en speciell typ av namnutrymme som garanterat identifieras vid kompileringen. När namnutrymmen skapas explicit identifieras de inte nödvändigtvis vid kompileringen.

I följande exempel används direktivet package för att skapa ett enkelt paket som innehåller en klass:

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

Namnet på klassen i det här exemplet är SampleCode. Eftersom klassen finns inuti exempelpaketet kvalificerar kompilatorn automatiskt klassnamnet vid kompileringen till det fullständiga, kvalificerade namnet samples.SampleCode. Kompilatorn kvalificerar också namnet på egenskaper eller metoder så att sampleGreeting och sampleFunction() blir samples.SampleCode.sampleGreeting respektive samples.SampleCode.sampleFunction().

Många utvecklare, särskilt de som har använt Java, väljer att placera bara klasser på den översta paketnivån. I ActionScript 3.0 kan du emellertid använda variabler, funktioner och även programsatser på den översta paketnivån och inte bara klasser. Ett avancerat sätt att använda den här funktionen är att definiera ett namnutrymme på den översta paketnivån, så att det blir tillgängligt för alla klasser i det paketet. Observera att bara två åtkomstspecifikationer, public och internal, tillåts på den översta paketnivån. I motsats till Java, där du kan deklarera kapslade klasser som privata, stöder ActionScript 3.0 varken kapslade eller privata klasser.

ActionScript 3.0-paket liknar på många sätt paket i programmeringsspråket Java. Som du ser i föregående exempel uttrycks fullständiga, kvalificerade paketreferenser med hjälp av punktoperatorn (.), på samma sätt som i Java. Du kan använda paket för att organisera din kod i en intuitiv hierarkisk struktur som kan användas av andra programmerare. Detta underlättar koddelning eftersom du kan skapa ett eget paket som du delar med andra, och du kan använda paket som skapats av andra i din kod.

När du använder paket blir de identifierarnamn du använder unika och hamnar inte i konflikt med andra identifierare. Somliga tycker att det här är den viktigaste fördelen med paket. Två programmerare som vill dela kod med varandra kan till exempel båda ha skapat en klass som heter SampleCode. Utan paket skulle detta skapa en namnkonflikt och den enda lösningen skulle vara att namnändra en av klasserna. Med paket undviks namnkonflikten genom att man placerar en, eller företrädesvis båda, klasserna i paket med unika namn.

Du kan också infoga inbäddade punkter i paketnamnet för att skapa kapslade paket. Då kan du skapa en hierarkisk paketorganisation. Ett bra exempel på detta är flash.display-paketet som ingår i ActionScript 3.0. Detta paket är kapslat inuti flash-paketet.

Det mesta i ActionScript 3.0 struktureras under flash-paketet. Paketet flash-display innehåller till exempel visningslist-API:n och paketet flash.events innehåller den nya händelsemodellen.

Skapa paket

ActionScript 3.0 är mycket flexibelt eftersom du kan organisera dina paket, klasser och källfiler. I tidigare versioner av ActionScript kunde du bara använda en klass per källfil och dessutom krävdes att namnet på källfilen matchade namnet på klassen. Med ActionScript 3.0 kan du ha flera klasser i samma källfil, men bara en klass i varje fil kan göras åtkomligt för kod som är extern för filen. Endast en klass i varje fil kan m.a.o. deklareras inuti en paketdeklaration. Du måste deklarera eventuella ytterligare klasser utanför paketdefinitionen, vilket gör att dessa klasser inte syns för kod som är utanför källfilen. Namnet på den klass som deklarerats inuti paketdefinitionen måste matcha namnet på källfilen.

ActionScript 3.0 är också mera flexibelt när det gäller att deklarera paket. I tidigare versioner av ActionScript representerade paket snarare kataloger i vilka du placerade källfiler, och du deklarerade inte paket med programsatsen package utan infogade paketnamnet som en del av det fullständiga, kvalificerade klassnamnet i klassdeklarationen. Även om paket fortfarande representerar kataloger i ActionScript 3.0 kan paket innehålla mer än just klasser. I ActionScript 3.0 använder du programsatsen package för att deklarera ett paket, vilket betyder att du också kan deklarera variabler, funktioner och namnutrymmen på den översta paketnivån. Du kan till och med infoga körbara programsatser på den översta paketnivån. Om du deklarerar variabler, funktioner eller namnutrymmen på den översta paketnivån är attributen public och internal de enda tillgängliga på den nivån, och attributet public kan bara användas av en enda paketnivådeklaration per fil, vare sig deklarationen är klass, variabel, funktion eller namnutrymme.

Du kan använda paket för att organisera kod och för att förhindra namnkonflikter. Du får inte blanda ihop begreppet paket med det orelaterade begreppet klassarv. Två klasser som finns i samma paket har ett gemensamt namnutrymme, men behöver inte vara relaterade till varandra på något annat sätt. På samma sätt har ett kapslat paket inte någon semantisk relation till sitt överordnade paket.

Importera paket

Om du vill använda en klass som finns inuti ett paket, måste du importera antingen paketet eller klassen. I ActionScript 2.0 behöver du inte importera klasser.

Vi kan använda klassen SampleCode som nämndes tidigare som exempel. Om klassen finns i ett paket som heter samples måste du använda någon av följande importprogramsatser innan du kan använda klassen SampleCode:

import samples.*;

eller

import samples.SampleCode;

Vanligtvis måste import-programsatser vara så specifika som möjligt. Om du bara vill använda klassen SampleCode från exempelpaketet, får du bara importera klassen SampleCode och inte hela paketet som klassen hör till. Om du importerar hela paket kan namnkonflikter uppstå.

Du måste också placera källkoden som definierar paketet eller klassen inuti din klassökväg. Klassökvägen är en användardefinierad lista med lokala katalogsökvägar, som anger var kompilatorn ska söka efter importerade paket och klasser. Klassökvägen kallas ibland byggsökväg eller källsökväg.

När du har importerat klassen eller paketet kan du använda antingen det fullständiga, kvalificerade namnet på klassen (samples.SampleCode) eller bara själva klassnamnet (SampleCode).

Du kan använda fullständiga, kvalificerade namn när klasser, metoder eller egenskaper med samma namn resulterar i tvetydig kod, men de kan vara svåra att hantera om de används för alla identifierare. Om du till exempel använder fullständiga, kvalificerade namn blir koden alltför detaljerad när du initierar klassinstansen SampleCode:

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

Vartefter nivån av kapslade paket ökar, minskar kodens läsbarhet. Om du är säker på att tvetydiga identifierare inte är något problem kan du använda enkla identifierare så att koden blir lättare att läsa. När du instansierar en ny instans av klassen SampleCode blir koden inte så detaljerad om du bara använder klassidentifieraren:

var mySample:SampleCode = new SampleCode();

Om du försöker använda identifierarnamn utan att först importera lämpligt paket eller lämplig klass kan klassdefinitionerna inte hittas av kompilatorn. Om du å andra sidan importerar ett paket eller en klass genereras ett fel om du försöker definiera ett namn som är i konflikt med ett importerat namn.

När du har skapat ett paket blir standardåtkomstspecifikationen för alla medlemmar i detta paket internal, vilket betyder att paketmedlemmarna bara visas för andra medlemmar i detta paket. Om du vill att en klass ska vara tillgänglig för kod utanför paketet, måste du deklarera klassen som public. Följande paket innehåller till exempel två klasser, SampleCode och CodeFormatter:

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

Klassen SampleCode visas utanför paketet eftersom det har deklarerats som en public-klass. Klassen CodeFormatter visas bara inuti själva exempelpaketet. Om du försöker öppna klassen CodeFormatter utanför exempelpaketet genereras ett felmeddelande, vilket visas i följande exempel:

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

Om du vill att båda klasserna ska vara tillgängliga utanför paketet måste du deklarera båda klasserna som public. Du kan inte använda attributet public på paketdeklarationen.

Du kan använda fullständiga, kvalificerade namn för att lösa de namnkonflikter som inträffar när du använder paket. Ett sådant scenario kan inträffa om du importerar två paket som definierar klasser med samma identifierare. Tänk dig följande paket som också har en klass som heter SampleCode:

package langref.samples 
{ 
    public class SampleCode {} 
}

Om du importerar båda klasserna uppstår en namnkonflikt när du använder klassen SampleCode:

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

Kompilatorn vet inte vilken SampleCode-klass som ska användas. För att lösa den här konflikten måste du använda det fullständiga, kvalificerade namnet på båda klasserna:

var sample1:samples.SampleCode = new samples.SampleCode(); 
var sample2:langref.samples.SampleCode = new langref.samples.SampleCode();
Obs! Programmerare som använt C++ använder ofta programsatsen import med #include. Direktivet #include är obligatoriskt i C++ eftersom C++-kompilatorn bearbetar en fil i taget och bara letar efter klassdefinitioner i andra filer om en rubrikfil ingår. ActionScript 3.0 har ett include-direktiv, men det importerar inte klasser och paket. Om du vill importera klasser och paket i ActionScript 3.0 måste du använda programsatsen import och placera källfilen som innehåller paketet i klassökvägen.

Namnutrymmen

Med namnutrymmen får du kontroll över hur egenskaper och metoder du skapar visas. Tänk på åtkomstkontrollsspecifikationerna public, private, protected och internal som inbyggda namnutrymmen. Om dessa fördefinierade specifikationer inte passar kan du skapa egna namnutrymmen.

Om du känner till XML-namnutrymmen är mycket av den här beskrivningen inte ny för dig, även om syntax och detaljer i ActionScript-implementeringen är litet annorlunda än i XML. Även om du inte har arbetat med namnutrymmen tidigare förstår du ändå själva begreppet, men implementeringen har en speciell terminologi som du måste lära dig.

Om du vill förstå hur namnutrymmen fungerar kan det vara bra att veta att namnet på en egenskap eller en metod består av två delar: en identifierare och ett namnutrymme. Identifieraren är det som du vanligtvis tänker på som ett namn. Identifieraren i följande klassdefinition är sampleGreeting och sampleFunction():

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

När definitioner föregås av ett namnutrymmesattribut är deras namn kvalificerat av standardnamnutrymmet internal, vilket betyder att de bara visas för anropare i samma paket. Om kompilatorn är inställd på strikt läge utfärdas en varning om att namnutrymmet internal tillämpas på alla identifierare som saknar ett namnutrymmesattribut. Om du vill vara säker på att en identifierare ska bli tillgänglig överallt, måste du lägga in attributet public före identifierarnamnet. I föregående exempelkod har både sampleGreeting och sampleFunction() namnutrymmesvärdet internal.

Du följer tre grundprinciper när du använder namnutrymmen. För det första måste du definiera namnutrymmet med nyckelordet namespace. I följande kod definieras till exempel namnutrymmet version1:

namespace version1;

För det andra använder du namnutrymmet i stället för en åtkomstkontrollsspecifikation i en egenskaps- eller metoddeklaration. I följande exempel placeras funktionen myFunction() i namnutrymmet version1:

version1 function myFunction() {}

För det tredje kan du, när du har tillämpat namnutrymmet, referera det med direktivet use eller genom att kvalificera namnet på en identifierare med ett namnutrymme. I följande exempel refereras funktionen myFunction() via direktivet use:

use namespace version1; 
myFunction();

Du kan också använda ett kvalificerat namn för att referera funktionen myFunction(), vilket visas i följande exempel:

version1::myFunction();

Definiera namnutrymmen

Namnutrymmen innehåller ett värde, URI (Uniform Resource Identifier), som ibland kallas namnutrymmesnamn. Med en URI kan du kontrollera att namnutrymmesdefinitionen är unik.

Du skapar ett namnutrymme genom att deklarera en namnutrymmesdefinition på ett av två sätt. Du kan antingen definiera namnutrymmet med en angiven URI, på samma sätt som du definierar ett XML-namnutrymme, eller också kan du utelämna detta URI. I följande exempel visas hur du definierar ett namnutrymme med en URI:

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

URI:n fungerar som en unik identifikationssträng för namnutrymmet. Om du, som i följande exempel, utelämnar URI:n skapar kompilatorn en unik intern identifikationssträng i stället för URI:n. Du har inte åtkomst till den här interna identifikationsfilen.

namespace flash_proxy;

När du har definierat ett namnutrymme, med eller utan en URI, kan namnutrymmet inte definieras om i samma omfång. Om du försöker definiera ett namnutrymme som tidigare har definierats i samma omfång genereras ett kompilatorfel.

Om ett namnutrymme definieras inuti ett paket eller en klass, visas det bara för kod utanför paketet eller klassen om lämplig åtkomstkontrollsspecifikation används. Följande kod visar namnutrymmet flash_proxy som definierats inuti paketet flash.utils. I följande exempel betyder avsaknaden av en åtkomstkontrollsspecifikation att namnutrymmet flash_proxy bara visas för kod inuti paketet flash.utils och inte för kod utanför paketet:

package flash.utils 
{ 
    namespace flash_proxy; 
}

I följande kod används attributet public för att visa namnutrymmet flash_proxy för kod utanför paketet:

package flash.utils 
{ 
    public namespace flash_proxy; 
}

Använda namnutrymmen

Att använda ett namnutrymme innebär att placera en definition i ett namnutrymme. Definitioner, som funktioner, variabler och konstanter, kan placeras i namnutrymmen (du kan inte placera en klass i ett anpassat namnutrymme).

En funktion kan till exempel deklareras med hjälp av åtkomstkontrollsspecifikationen public. Om du använder attributet public i en funktionsdefinition placeras funktionen i det allmänna namnutrymmet, vilket gör att funktionen blir tillgänglig för all kod. När du har definierat ett namnutrymme kan du använda namnutrymmet på samma sätt som du använder attributet public, och definitionen blir tillgänglig för kod som kan referera till ditt anpassade namnutrymme. Om du till exempel definierar namnutrymmet example1 kan du lägga till metoden myFunction() och använda example1 som ett attribut, vilket visas i följande exempel:

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

Att deklarera metoden myFunction() och använda namnutrymmet example1 som ett attribut betyder att metoden hör till namnutrymmet example1.

Du måste tänka på följande när du använder namnutrymmen:

  • Du kan bara använda ett namnutrymme för varje deklaration.

  • Du kan inte använda ett namnutrymmesattribut för mer än en definition i taget. Om du vill använda namnutrymmet på tio olika funktioner måste du alltså lägga till namnutrymmet som ett attribut i alla tio funktionsdefinitionerna.

  • Om du använder ett namnutrymme kan du inte ange en åtkomstkontrollsspecifikation samtidigt, eftersom namnutrymmen och åtkomstkontrollsspecifikationer inte kan kombineras. Du kan alltså inte deklarera en funktion eller en egenskap som public, private, protected eller internal när du samtidigt använder namnutrymmet.

Referera namnutrymmen

Du behöver inte explicit referera ett namnutrymme när du använder en metod eller en egenskap som deklarerats med någon av åtkomstkontrollsnamnutrymmena, till exempel public, private, protected och internal. Detta beror på att åtkomsten till dessa speciella namnutrymmen styrs av sammanhanget. Definitioner som placerats i namnutrymmet private blir till exempel automatiskt tillgängliga för kod i samma klass. Det finns däremot ingen sådan sammanhangskänslighet för de namnutrymmen du definierar. Om du vill använda en metod eller egenskap som du har placerat i ett anpassat namnutrymme, måste du referera till namnutrymmet.

Du kan referera namnutrymmen med direktivet use namespace och du kan kvalificera namnet med namnutrymmet med hjälp av namnkvalificeringstecknet (::). Om du refererar ett namnutrymme med direktivet use namespace ”öppnas” namnutrymmet, så att det kan användas på alla identifierare som inte är kvalificerade. Om du har definierat namnutrymmet example1 kan du öppna namnet i namnutrymmet genom att använda use namespace example1:

use namespace example1; 
myFunction();

Du kan öppna flera namnutrymmen samtidigt. När du har öppnat ett namnutrymme med use namespace förblir det öppet i hela kodblocket som det öppnats i. Det finns inget sätt att explicit stänga ett namnutrymme.

Om du har flera öppna namnutrymmen ökar emellertid risken för namnkonflikter. Om du föredrar att inte öppna ett namnutrymme, kan du undvika direktivet use namespace genom att kvalificera metod- eller egenskapsnamnet med namnutrymmet och namnkvalificeringstecknet. I följande kod visas hur du kan kvalificera namnet myFunction() med namnutrymmet example1:

example1::myFunction();

Använda namnutrymmen

Du hittar ett verkligt exempel på ett namnutrymme som används för att förhindra namnkonflikter i klassen flash.utils.Proxy som ingår i ActionScript 3.0. Klassen Proxy ersätter egenskapen Object.__resolve från ActionScript 2.0, gör att du kan avbryta referenser till odefinierade egenskaper eller metoder innan ett fel inträffar. Alla metoder för klassen Proxy finns i namnutrymmet flash_proxy för att förhindra namnkonflikter.

För att du bättre ska kunna förstå hur namnutrymmet flash_proxy används, måste du förstå hur klassen Proxy ska användas. Klassen Proxys funktioner är bara tillgängliga för klasser som ärver från denna klass. Om du vill använda metoderna i klassen Proxy på ett objekt, måste objektets klassdefinition utöka klassen Proxy. Om du till exempel vill avbryta försök till anrop av en odefinierad metod, utökar du klassen Proxy och sedan åsidosätter du metoden callProperty() i klassen Proxy.

Du kanske kommer ihåg att implementering av namnutrymmen vanligtvis är en trestegsprocess som består av att definiera, använda och referera ett namnutrymme. Eftersom du aldrig explicit anropar någon av klassen Proxys metoder, kommer namnutrymmet flash_proxy att definieras och användas, men inte att refereras. ActionScript 3.0 definierar namnutrymmet flash_proxy och använder det i klassen Proxy. Din kod behöver bara använda namnutrymmet flash_proxy på klasser som utökar klassen Proxy.

Namnutrymmet flash_proxy definieras i paketet flash.utils på ett sätt som liknar detta:

package flash.utils 
{ 
    public namespace flash_proxy; 
}

Namnutrymmet används på metoderna i klassen Proxy enligt följande utdrag ur klassen Proxy:

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

Som följande kod visar måste du först importera både klassen Proxy och namnutrymmet flash_proxy. Du måste deklarera klassen så att den utökar klassen Proxy (du måste alltså lägga till attributet dynamic om du kompilerar i strikt läge). När du åsidosätter metoden callProperty() måste du använda namnutrymmet flash_property.

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

Om du skapar en instans av klassen MyProxy och anropar en odefinierad metod, till exempel metoden testing(), som anropas i följande exempel, kommer objektet Proxy att avbryta metodanropet och köra programsatserna inuti den åsidosatta metoden callProperty() (i det här fallet en enkel trace()-programsats).

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

Det finns två fördelar med att ha metoder av klassen Proxy inuti namnutrymmet flash_proxy. Om du för det första har ett separat namnutrymme minskas skräpet i det gemensamma gränssnittet för en klass som utökar klassen Proxy. (Det finns ungefär ett dussin metoder i klassen Proxy som du kan åsidosätta, och ingen av dem kan anropas direkt. Om du placerar dem i det allmänna namnutrymmet blir det konstigt.) Om du för det andra använder namnutrymmet flash_proxy undviker du namnkonflikter om underklassen till Proxy innehåller instansmetoder med samma namn som någon av metoderna i klassen Proxy. Du kan till exempel vilja kalla en av dina metoder callProperty(). Följande kod godkänns eftersom din version av metoden callProperty() finns i ett annat namnutrymme:

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

Det kan också vara bra att använda namnutrymmen när du vill ha åtkomst till metoder och egenskaper på ett sätt som inte kan uppnås med de fyra åtkomstkontrollsspecifikationerna (public, private, internal och protected). Det finns till exempel några verktygsfunktioner som är spridda över flera paket. Du vill att alla dessa metoder ska vara tillgängliga för alla dina paket, men du vill inte att metoderna ska vara allmänna. För att uppnå detta kan du skapa ett namnutrymme och använda det som en egen speciell åtkomstkontrollsspecifikation.

I följande exempel används ett användardefinierat namnutrymme för att gruppera två funktioner som finns i olika paket. Genom att gruppera dem i samma namnutrymme, kan du göra båda funktionerna synliga för en klass eller ett paket via en enda use namespace-programsats.

I det här exemplet används fyra filer för att visa den här tekniken. Alla filerna måste ligga i din klassökväg. Den första filen, myInternal.as, används för att definiera namnutrymmet myInternal. Eftersom filen finns i ett paket som heter example, måste du placera filen i en mapp som heter example. Namnutrymmet markeras som public så att det kan importeras till andra paket.

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

Den andra och tredje filen, Utility.as och Helper.as, definierar de klasser som innehåller metoder som ska vara tillgängliga för andra paket. Klassen Utility finns i paketet example.alpha, vilket betyder att filen ska placeras i en mapp som heter alpha som är en undermapp till mappen example. Klassen Helper finns i paketet example.beta, vilket betyder att filen ska placeras i en mapp som heter beta som också är en undermapp till mappen example. Båda dessa paket, example.alpha och example.beta, måste importera namnutrymmet innan de kan använda det.

// 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; 
        } 
    } 
}

Den fjärde filen, NamespaceUseCase.as, är huvudprogramklassen och ska ligga på samma nivå som mappen example. I Flash Professional används den här klassen som dokumentklass för FLA. Klassen NamespaceUseCase importerar också namnutrymmet myInternal och använder det för att anropa de två statiska metoderna som finns i andra paket. I exemplet används statiska metoder bara för att förenkla koden. Både statiska metoder och instansmetoder kan placeras i namnutrymmet myInternal.

// 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] 
        } 
    } 
}