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