Met naamruimten kunt u de zichtbaarheid beheren van de eigenschappen en methoden die u maakt. U kunt de toegangsbeheerspecificaties
public
,
private
,
protected
en
internal
zien als ingebouwde naamruimten. Als deze vooraf gedefinieerde toegangsbeheerspecificaties niet voldoen aan uw behoeften, kunt u zelf naamruimten maken.
Als u ervaring hebt met XML-naamruimten, zal het meeste u bekend voorkomen. De syntaxis en details voor de implementatie van ActionScript verschillen echter iets van die van XML. Als u nog nooit met naamruimten hebt gewerkt, zult u merken dat het concept zelf eenvoudig is, maar dat bij de implementatie specifieke terminologie wordt gebruikt die u moet leren kennen.
Als u wilt begrijpen hoe naamruimten werken, is het nuttig om te weten dat de naam van een eigenschap of methode altijd twee gedeelten bevat: een id en een naamruimte. De id is wat gewoonlijk als naam wordt beschouwd. De id's in de volgende klassendefinitie zijn bijvoorbeeld
sampleGreeting
en
sampleFunction()
:
class SampleCode
{
var sampleGreeting:String;
function sampleFunction () {
trace(sampleGreeting + " from sampleFunction()");
}
}
Wanneer definities niet door een naamruimte-attribuut worden voorafgegaan, worden de namen ervan gekwalificeerd door de standaardnaamruimte
internal
. Dit betekent dat ze alleen zichtbaar zijn voor aanroepende elementen in hetzelfde pakket. Als de compiler is ingesteld op de strikte modus, wordt een waarschuwing weergegeven dat de naamruimte
internal
van toepassing is op alle id's zonder naamruimte-attribuut. Als u een id overal beschikbaar wilt maken, moet u de id-naam specifiek vooraf laten gaan door het attribuut
public
. In de voorgaande voorbeeldcode hebben zowel
sampleGreeting
als
sampleFunction()
de naamruimtewaarde
internal
.
Er zijn drie basisstappen voor het gebruiken van naamruimten. Als eerste stap definieert u de naamruimte met behulp van het trefwoord
namespace
. Met de volgende code wordt bijvoorbeeld de naamruimte
version1
gedefinieerd:
namespace version1;
Als tweede stap past u de naamruimte toe door deze te gebruiken in plaats van een toegangsbeheerspecificatie in een eigenschap- of methodedeclaratie. In het volgende voorbeeld wordt een functie met de naam
myFunction()
in de naamruimte
version1
geplaatst:
version1 function myFunction() {}
Als derde stap, nadat u de naamruimte hebt toegepast, kunt u ernaar verwijzen met de aanwijzing
use
of door de naam van een id met een naamruimte te kwalificeren. In het volgende voorbeeld wordt naar een functie met de naam
myFunction()
verwezen met behulp van de aanwijzing
use
:
use namespace version1;
myFunction();
U kunt ook een gekwalificeerde naam gebruiken om te verwijzen naar de functie
myFunction()
, zoals in het volgende voorbeeld wordt getoond:
version1::myFunction();
Naamruimten definiëren
Naamruimten bevatten één waarde, de URI (Uniform Resource Identifier), ook wel de
naamruimtenaam
genoemd. Met een URI weet u zeker dat de naamruimtedefinitie uniek is.
U maakt een naamruimte door op een van de twee mogelijke manieren een naamruimtedefinitie te declareren. U kunt een naamruimte definiëren met een expliciete URI, zoals bij een XML-naamruimte, of u kunt de URI weglaten. Het volgende voorbeeld laat zien hoe u een naamruimte kunt definiëren met een URI:
namespace flash_proxy = "http://www.adobe.com/flash/proxy";
De URI dient als unieke id-tekenreeks voor de naamruimte. Als u de URI weglaat, zoals in het volgende voorbeeld, wordt door de compiler een unieke interne id-tekenreeks gemaakt in plaats van de URI. U hebt geen toegang tot deze interne id-tekenreeks.
namespace flash_proxy;
Nadat u een naamruimte hebt gedefinieerd, met of zonder URI, kunt u die naamruimte niet opnieuw definiëren in hetzelfde bereik. Een poging om een naamruimte te definiëren die al in hetzelfde bereik is gedefinieerd, resulteert in een compilatiefout.
Als een naamruimte is gedefinieerd binnen een pakket of een klasse, is de naamruimte mogelijk niet zichtbaar voor code buiten dat pakket of de klasse, tenzij de juiste toegangsbeheerspecificatie wordt gebruikt. Met de volgende code wordt bijvoorbeeld de naamruimte
flash_proxy
getoond, gedefinieerd binnen het pakket flash.utils. In het voorbeeld betekent het ontbreken van een toegangsbeheerspecificatie dat de naamruimte
flash_proxy
alleen zichtbaar is voor code binnen het pakket flash.utils en niet voor andere code buiten het pakket:
package flash.utils
{
namespace flash_proxy;
}
Met de volgende code wordt het attribuut
public
gebruikt om de naamruimte
flash_proxy
zichtbaar te maken voor code buiten het pakket:
package flash.utils
{
public namespace flash_proxy;
}
Naamruimten toepassen
Een naamruimte toepassen betekent een definitie plaatsen in een naamruimte. Definities die u in naamruimten kunt plaatsen zijn functies, variabelen en constanten (u kunt geen klasse in een aangepaste naamruimte plaatsen).
Neem bijvoorbeeld een functie die is gedeclareerd met de toegangsbeheernaamruimte
public
. Door het gebruik van het attribuut
public
in een functiedefinitie wordt de functie in de naamruimte public geplaatst en is zo beschikbaar voor alle code. Nadat u een naamruimte hebt gedefinieerd, kunt u de gedefinieerde naamruimte net zo gebruiken als het attribuut
public
. De definitie is dan beschikbaar voor code die naar de aangepaste naamruimte kan verwijzen. Als u bijvoorbeeld een naamruimte
example1
definieert, kunt u een methode met de naam
myFunction()
toevoegen door
example1
als attribuut te gebruiken, zoals in het volgende voorbeeld wordt getoond:
namespace example1;
class someClass
{
example1 myFunction() {}
}
Door de methode
myFunction()
te declareren met de naamruimte
example1
als attribuut, behoort de methode tot de naamruimte
example1
.
Let op het volgende wanneer u naamruimten toepast:
-
U kunt slechts één naamruimte toepassen op elke declaratie.
-
U kunt een naamruimte-attribuut nooit op meer dan één definitie tegelijk toepassen. Met andere woorden, als u een naamruimte wilt toepassen op tien verschillende functies, moet u de naamruimte als attribuut toevoegen aan elk van de tien functiedefinities.
-
Als u een naamruimte toepast, kunt u geen toegangsbeheerspecificatie opgeven, omdat naamruimten en toegangsbeheerspecificaties elkaar uitsluiten. Met andere woorden, u kunt een functie of eigenschap niet declareren als
public
,
private
,
protected
of
internal
nadat u de naamruimte hebt toegepast.
Verwijzen naar naamruimten
U hoeft niet expliciet naar een naamruimte te verwijzen wanneer u een methode of eigenschap gebruikt die wordt gedeclareerd met een van de toegangsbeheernaamruimten, zoals
public
,
private
,
protected
en
internal
. Dat komt doordat de toegang tot deze speciale naamruimten wordt bepaald door de context. Definities die bijvoorbeeld in de naamruimte
private
worden geplaatst, zijn automatisch beschikbaar voor code binnen dezelfde klasse. Voor naamruimten die u zelf definieert, bestaat een dergelijke contextgevoeligheid echter niet. Als u een methode of eigenschap wilt gebruiken die u in een aangepaste naamruimte hebt geplaatst, moet u naar de naamruimte verwijzen.
U kunt naar naamruimten verwijzen met de aanwijzing
use namespace
of u kunt de naam met de naamruimte kwalificeren met behulp van het naamkwalificatieteken (
::
). Door naar een naamruimte te verwijzen met de aanwijzing
use namespace
wordt de naamruimte 'geopend'. Zo kan de naamruimte worden toegepast op alle id's die niet zijn gekwalificeerd. Als u bijvoorbeeld de naamruimte
example1
hebt gedefinieerd, hebt u toegang tot namen in die naamruimte door
use namespace example1
te gebruiken:
use namespace example1;
myFunction();
U kunt meerdere naamruimten tegelijk openen. Nadat u een naamruimte hebt geopend met
use namespace
, blijft deze open voor het blok met code waarin de naamruimte is geopend. U kunt een naamruimte niet expliciet sluiten.
Als u meer dan één naamruimte open hebt, neemt de kans op naamconflicten echter toe. Als u een naamruimte liever niet wilt openen, kunt u de aanwijzing
use namespace
vermijden door de naam van de methode of eigenschap met de naamruimte en het naamkwalificatieteken te kwalificeren. Met de volgende code wordt bijvoorbeeld getoond hoe u de naam
myFunction()
met de naamruimte
example1
kunt kwalificeren:
example1::myFunction();
Naamruimten gebruiken
U vindt een praktijkvoorbeeld van een naamruimte die wordt gebruikt om naamconflicten te voorkomen in de klasse flash.utils.Proxy die deel uitmaakt van ActionScript 3.0. Met de klasse Proxy, die de vervanging is van de eigenschap
Object.__resolve
eigenschap in ActionScript 2.0, waarmee u verwijzingen naar niet-gedefinieerde eigenschappen of methoden onderscheppen voordat een fout optreedt. Alle methoden van de klasse Proxy bevinden zich in de naamruimte
flash_proxy
om naamconflicten te voorkomen.
Voor een beter begrip van hoe de naamruimte
flash_proxy
wordt gebruikt, moet u weten hoe u de klasse Proxy gebruikt. De functionaliteit van de klasse Proxy is alleen beschikbaar voor klassen die ervan overerven. Met andere woorden, als u de methoden van de klasse Proxy voor een ander object wilt gebruiken, moet de klassendefinitie van het object de klasse Proxy uitbreiden. Als u bijvoorbeeld pogingen om een ongedefinieerde methode aan te roepen wilt onderscheppen, breidt u de klasse Proxy uit en overschrijft u vervolgens de methode
callProperty()
van de klasse Proxy.
Zoals eerder is besproken, bestaat het implementeren van naamruimten doorgaans uit drie stappen: definiëren, toepassen en ernaar verwijzen. Omdat u de methoden van de klasse Proxy echter nooit expliciet aanroept, wordt de naamruimte
flash_proxy
alleen gedefinieerd en toegepast, maar wordt er niet naar verwezen. ActionScript 3.0 definieert de naamruimte
flash_proxy
en past deze toe in de klasse Proxy. De code hoeft de naamruimte
flash_proxy
alleen toe te passen op klassen die de klasse Proxy uitbreiden.
De naamruimte
flash_proxy
wordt ongeveer als volgt gedefinieerd in het pakket flash.utils:
package flash.utils
{
public namespace flash_proxy;
}
De naamruimte wordt toegepast op de methoden van de klasse Proxy zoals in het volgende fragment van de klasse Proxy wordt getoond:
public class Proxy
{
flash_proxy function callProperty(name:*, ... rest):*
flash_proxy function deleteProperty(name:*):Boolean
...
}
Zoals de volgende code laat zien, moet u eerst de klasse Proxy en de naamruimte
flash_proxy
importeren. Vervolgens moet u de klasse zo declareren dat deze de klasse Proxy uitbreidt (u moet ook het attribuut
dynamic
toevoegen als u in de strikte modus compileert). Wanneer u de methode
callProperty()
overschrijft, moet u de naamruimte
flash_proxy
gebruiken.
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);
}
}
}
Als u een instantie van de klasse MyProxy maakt en een ongedefinieerde methode aanroept, zoals de aangeroepen methode
testing()
in het volgende voorbeeld, onderschept het object Proxy de methodeaanroep en worden de instructies binnen de overschreven methode
callProperty()
uitgevoerd (in dit geval een eenvoudige instructie
trace()
).
var mySample:MyProxy = new MyProxy();
mySample.testing(); // method call intercepted: testing
Er zijn twee voordelen verbonden aan het opnemen van de klasse Proxy binnen de naamruimte
flash_proxy
. Ten eerste vermindert een aparte naamruimte de hoeveelheid rommelige code in de openbare interface van de klassen die de klasse Proxy uitbreiden. (Er zijn meer dan tien methoden in de klasse Proxy die u kunt overschrijven en die u niet rechtstreeks kunt aanroepen. Het plaatsen van al deze methoden in de naamruimte public zou tot verwarring kunnen leiden.) Ten tweede voorkomt het gebruik van de naamruimte
flash_proxy
naamconflicten in het geval dat de subklasse Proxy instantiemethoden bevat met namen die overeenkomen met een van de methoden van de klasse Proxy. U wilt bijvoorbeeld een van uw eigen methoden
callProperty()
noemen. De volgende code is acceptabel, omdat uw versie van de methode
callProperty()
zich in een andere naamruimte bevindt:
dynamic class MyProxy extends Proxy
{
public function callProperty() {}
flash_proxy override function callProperty(name:*, ...rest):*
{
trace("method call intercepted: " + name);
}
}
Naamruimten kunnen ook nuttig zijn wanneer u voor toegang wilt zorgen tot methoden of eigenschappen op een manier die niet mogelijk is met de vier toegangsbeheerspecificaties (
public
,
private
,
internal
en
protected
). U hebt bijvoorbeeld enkele hulpprogrammamethoden verspreid over diverse pakketten. U wilt deze methoden beschikbaar maken voor alle pakketten, maar ze niet als public declareren. U kunt voor dit doel een naamruimte maken en gebruiken als uw eigen speciale toegangsbeheerspecificatie.
In het volgende voorbeeld wordt een door de gebruiker gedefinieerde naamruimte gebruikt om twee functies in verschillende pakketten te groeperen. Door de twee functies in dezelfde naamruimte te groeperen, kunt u ze beide zichtbaar maken voor een klasse of pakket met behulp van een instructie
use namespace
.
In dit voorbeeld worden vier bestanden gebruikt om deze techniek te demonstreren. Al deze bestanden moeten in uw klassenpad zijn opgenomen. Met het eerste bestand, myInternal.as, wordt de naamruimte
myInternal
gedefinieerd. Het bestand bevindt zich in een pakket met de naam example, zodat u het bestand in een map met de naam example moet plaatsen. De naamruimte is gemarkeerd als
public
, zodat deze in andere pakketten kan worden geïmporteerd.
// myInternal.as in folder example
package example
{
public namespace myInternal = "http://www.adobe.com/2006/actionscript/examples";
}
Het tweede en derde bestand, Utility.as en Helper.as, definiëren de klassen met de methoden die beschikbaar moeten zijn voor andere pakketten. De klasse Utility bevindt zich in het pakket example.alpha. Dit betekent dat het bestand in een map moet worden geplaatst met de naam alpha die een submap is van de map example. De klasse Helper bevindt zich in het pakket example.beta. Dit betekent dat het bestand in een map moet worden geplaatst met de naam beta die eveneens een submap is van de map example. Beide pakketten, example.alpha en example.beta, moeten de naamruimte importeren voordat deze wordt gebruikt.
// 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;
}
}
}
Het vierde bestand, NamespaceUseCase.as, is de hoofdtoepassingsklasse en moet op hetzelfde niveau zijn als de map example. In Flash Professional zou deze klasse worden gebruikt als de documentklasse voor het FLA-bestand. De klasse NamespaceUseCase importeert bovendien de naamruimte
myInternal
en gebruikt deze om de twee statische methoden op te roepen die zich in de andere pakketten bevinden. In het voorbeeld worden alleen statische methoden gebruikt om de code eenvoudig te houden. U kunt zowel statische methoden als instantiemethoden in de naamruimte
myInternal
plaatsen.
// 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]
}
}
}