Een klasse is een abstracte representatie van een object. Een klasse slaat informatie op over het type gegevens dat een object kan bevatten en het gedrag dat een object kan vertonen. Het nut van een dergelijke abstractie is mogelijk niet duidelijk wanneer u kleine scripts schrijft die slechts een paar met elkaar communicerende objecten bevatten. Als het bereik van een programma groeit, neemt het aantal objecten dat beheerd moet worden toe. In dat geval kunt u met behulp van klassen beter bepalen hoe objecten worden gemaakt en hoe ze met elkaar communiceren.
In het verouderde ActionScript 1.0 konden ActionScript-ontwikkelaars objecten Function gebruiken om constructies te maken die op klassen leken. In ActionScript 2.0 werd formele ondersteuning toegevoegd voor klassen met trefwoorden zoals
class
en
extends
. ActionScript 3.0 blijft de trefwoorden van ActionScript 2.0 ondersteunen en voegt nieuwe mogelijkheden toe. ActionScript 3.0 bevat bijvoorbeeld een verbeterde toegangscontrole met de attributen
protected
en
internal
. Dit biedt ook een betere controle over overerving met de trefwoorden
final
en
Negeren
.
Voor ontwikkelaars die klassen hebben gemaakt in programmeertalen zoals Java, C++ of C# biedt ActionScript een bekende ervaring. ActionScript heeft veel dezelfde trefwoorden en attribuutnamen, zoals
class
,
extends
en
public
.
Opmerking:
In de Adobe ActionScript-documentatie staat de term eigenschap voor een lid van een object of klasse, inclusief variabelen, constanten en methoden. Hoewel vaak geen onderscheid wordt gemaakt tussen de termen class en static, hebben ze hier verschillende betekenissen. In dit voorbeeld verwijst de woordgroep 'eigenschappen van een klasse' bijvoorbeeld naar alle leden van een klasse, in plaats van alleen naar leden van het type static.
Klassendefinities
Klassendefinities in ActionScript 3.0 gebruiken syntaxis die overeenkomt met de syntaxis die werd gebruikt voor klassendefinities in ActionScript 2.0. De juiste syntaxis voor een klassendefinitie roept het trefwoord
class
aan, gevolgd door de naam van de klasse. De hoofdtekst van de klasse, die door accolades (
{}
) wordt ingesloten, volgt de naam van de klasse. De volgende code maakt bijvoorbeeld een klasse met de naam Shape die een variabele bevat, met de naam
visible
:
public class Shape
{
var visible:Boolean = true;
}
Een belangrijke syntaxiswijziging betreft de klassendefinities in een pakket. Als in ActionScript 2.0 een klasse zich in een pakket bevindt, moet de pakketnaam in de klassendeclaratie zijn opgenomen. In ActionScript 3.0 is de instructie
package
geïntroduceerd en moet de pakketnaam in de pakketdeclaratie zijn opgenomen in plaats van in de klassendeclaratie. De volgende klassendeclaraties tonen bijvoorbeeld hoe de klasse BitmapData, deel van het pakket flash.display, in ActionScript 2.0 en ActionScript 3.0 wordt gedefinieerd:
// ActionScript 2.0
class flash.display.BitmapData {}
// ActionScript 3.0
package flash.display
{
public class BitmapData {}
}
Klassenattributen
Met ActionScript 3.0 kunt u klassendefinities met een van de volgende vier attributen bewerken:
attribuut
|
Definitie
|
dynamic
|
Hiermee kunnen eigenschappen bij uitvoering aan instanties worden toegevoegd.
|
final
|
Mag niet door een andere klasse worden uitgebreid.
|
internal
(standaard)
|
Zichtbaar voor verwijzingen binnen het huidige pakket.
|
public
|
Zichtbaar voor alle verwijzingen.
|
Voor elk van deze attributen, behalve
internal
, moet u expliciet het attribuut opnemen om het gekoppelde gedrag op te halen. Als u bijvoorbeeld niet het attribuut
dynamic
opneemt wanneer u een klasse definieert, kunt u bij uitvoering geen eigenschappen aan een klasseninstantie toevoegen. U wijst een attribuut expliciet toe door deze aan het begin van de klassendefinitie te plaatsen, zoals getoond in de volgende code:
dynamic class Shape {}
In de lijst is het attribuut
abstract
niet opgenomen. Abstracte klassen worden niet ondersteund in ActionScript 3.0. Verder bevat de lijst ook geen attributen
private
en
protected
. Deze attributen zijn alleen belangrijk in een klassendefinitie en kunnen zelf niet op klassen worden toegepast. Als u niet wilt dat een klasse buiten een pakket zichtbaar is voor gebruikers, plaatst u de klasse in een pakket en markeert u de klasse met het attribuut
internal
. U kunt ook de attributen
internal
en
public
weglaten. De compiler voegt in dat geval automatisch het attribuut
internal
toe. U kunt ook een klasse definiëren zodat deze alleen zichtbaar is binnen het gedefinieerde bronbestand. Plaats de klasse onderaan in uw bronbestand, onder de accolade sluiten van de pakketdefinitie.
Hoofdtekst van de klasse
De hoofdtekst van de klasse is ingesloten door accolades. Hierin worden de variabelen, constanten en methoden van uw klasse gedefinieerd. Het volgende voorbeeld geeft de declaratie weer van de Toegankelijkheidsklasse in ActionScript 3.0:
public final class Accessibility
{
public static function get active():Boolean;
public static function updateProperties():void;
}
U kunt ook een naamruimte definiëren binnen de hoofdtekst van een klasse. Het volgende voorbeeld toont hoe een naamruimte binnen de hoofdtekst van een klasse kan worden gedefinieerd en gebruikt als een attribuut van een methode in die klasse:
public class SampleClass
{
public namespace sampleNamespace;
sampleNamespace function doSomething():void;
}
Met ActionScript 3.0 kunt u niet alleen definities in de hoofdtekst van een klasse opnemen, maar ook instructies. Instructies in de hoofdtekst van een klasse maar buiten een methodedefinitie worden precies één keer uitgevoerd. Deze uitvoering vindt plaats wanneer de klassedefinitie voor het eerst wordt herkend en het gerelateerde klassenobject wordt gemaakt. Het volgende voorbeeld bevat een aanroep naar een externe functie
hello()
en een instructie
trace
die een bevestiging weergeeft wanneer de klasse is gedefinieerd:
function hello():String
{
trace("hola");
}
class SampleClass
{
hello();
trace("class created");
}
// output when class is created
hola
class created
In ActionScript 3.0 is het toegestaan om in dezelfde hoofdtekst van een klasse een statische eigenschap en een instantie-eigenschap met dezelfde naam te definiëren. De volgende code declareert bijvoorbeeld een variabele van het type static met de naam
message
en een instantievariabele met dezelfde naam:
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
Attributen voor klasseneigenschappen
In beschrijvingen van het ActionScript-objectmodel staat de term
eigenschap
voor alles wat een lid van een klasse kan zijn, inclusief variabelen, constanten en methoden. In de Naslaggids voor Adobe ActionScript 3.0 voor het Adobe Flash-platform wordt deze term strikter toegepast. In die context omvat de term Eigenschap alleen leden van klassen die variabelen zijn of worden gedefinieerd door een methode getter/setter. In ActionScript 3.0 hebt u een set attributen die voor elke eigenschap van een klasse kunnen worden gebruikt. De volgende tabel somt deze attributen op.
Attribuut
|
Definitie
|
internal
(standaard)
|
Zichtbaar voor verwijzingen binnen hetzelfde pakket.
|
private
|
Zichtbaar voor verwijzingen in dezelfde klasse.
|
protected
|
Zichtbaar voor verwijzingen in dezelfde klasse en afgeleide klassen.
|
public
|
Zichtbaar voor alle verwijzingen.
|
static
|
Hiermee wordt opgegeven dat een eigenschap tot een klasse behoort, in tegenstelling tot de instanties van een klasse.
|
UserDefinedNamespace
|
Aangepaste naam voor naamruimte, die door de gebruiker is gedefinieerd.
|
Naamruimte-attributen voor toegangsbeheer
ActionScript 3.0 bevat vier speciale attributen die de toegang beheren tot eigenschappen die binnen een klasse zijn gedefinieerd:
public
,
private
,
protected
en
internal
.
Het attribuut
public
maakt een eigenschap in uw script zichtbaar. Als u bijvoorbeeld een methode buiten zijn pakket zichtbaar wilt maken voor code, moet u de methode met het attribuut
public
declareren. Dit gaat voor alle eigenschappen op, ongeacht of ze zijn gedeclareerd met het trefwoord
var
,
const
of
function
.
Het attribuut
private
maakt een eigenschap alleen zichtbaar voor aanroepen binnen de definiërende klasse van de eigenschap. Dit gedrag verschilt van het gedrag van het attribuut
private
in ActionScript 2.0, die een subklasse toegang bood tot een eigenschap van het type private in een superklasse. Een andere belangrijke gedragsverandering heeft te maken met toegang bij uitvoering. In ActionScript 2.0 werd met het trefwoord
private
alleen toegang toegestaan tijdens het compileren, wat bij uitvoering eenvoudig te omzeilen was. In ActionScript 3.0 is dit niet langer zo. Eigenschappen die zijn gemarkeerd als
private
, zijn zowel tijdens het compileren als bij uitvoering niet beschikbaar.
De volgende code maakt bijvoorbeeld een eenvoudige klasse met de naam PrivateExample met een variabele van het type private en probeert vervolgens de variabele van buitenaf de klasse te benaderen.
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 is het verkrijgen van toegang tot een eigenschap van het type private met gebruik van de puntoperator (
myExample.privVar
) resulteert in een fout bij compilatie als u de strikte modus gebruikt. Anders wordt de fout bij uitvoering gerapporteerd, op dezelfde manier als wanneer u de operator voor eigenschaptoegang (
myExample["privVar"]
) zou gebruiken.
De volgende tabel bevat de resultaten van een poging om een eigenschap van het type private te benaderen die tot een verzegelde (niet dynamische) klasse behoort:
|
Strikte modus
|
Standaardmodus
|
puntoperator (
.
)
|
fout bij compilatie
|
uitvoeringsfout
|
haakjesoperator (
[]
)
|
uitvoeringsfout
|
uitvoeringsfout
|
Voor klassen die zijn gedeclareerd met het attribuut
dynamic
, resulteren pogingen tot het verkrijgen van toegang tot een variabele van het type private niet in een uitvoerfout. De variabele is in plaats daarvan niet zichtbaar, zodat het de waarde
undefined
oplevert. Er treedt echter een fout bij compilatie op als u de puntoperator in de strikte modus gebruikt. Het volgende voorbeeld is hetzelfde als het vorige voorbeeld, behalve dat de klasse PrivateExample als een klasse van het type dynamic is gedeclareerd:
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
Dynamische klassen retourneren doorgaans de waarde
undefined
in plaats van dat ze een fout genereren wanneer externe code toegang probeert te krijgen tot een eigenschap van het type private. De volgende tabel toont dat er alleen een fout wordt gegenereerd wanneer de puntoperator in de strikte modus wordt gebruikt om toegang tot een eigenschap van het type private te krijgen:
|
Strikte modus
|
Standaardmodus
|
puntoperator (
.
)
|
fout bij compilatie
|
undefined
|
haakjesoperator (
[]
)
|
undefined
|
undefined
|
Het attribuut
protected
, nieuw in ActionScript 3.0, maakt een eigenschap zichtbaar voor aanroepers binnen zijn eigen klasse of in een subklasse. Een eigenschap van het type protected is met andere woorden binnen zijn eigen klasse beschikbaar of voor klassen die onder deze klasse in de overervingshiërarchie liggen. Dit is waar ongeacht of de subklasse zich in hetzelfde pakket bevindt of in een ander pakket.
Voor degenen die bekend zijn met ActionScript 2.0, is deze functionaliteit vergelijkbaar met het attribuut
private
in ActionScript 2.0. Het attribuut van ActionScript 3.0
protected
is ook vergelijkbaar met het attribuut
protected
in Java. Het verschil met de Java-versie staat ook toegang toe aan oproepers met hetzelfde pakket. Het attribuut
protected
is nuttig wanneer u met een variabele of methode werkt die uw subklassen nodig hebben, maar u deze wilt verbergen voor code die geen deel uitmaakt van de overervingsketen.
Het attribuut
internal
, nieuw in ActionScript 3.0, maakt een eigenschap zichtbaar voor aanroepers binnen zijn eigen pakket. Dit is het standaardattribuut voor code binnen een pakket en geldt voor alle eigenschappen die niet een van de volgende attributen bevatten:
Het attribuut
internal
lijkt op het standaardtoegangsbeheer in Java, hoewel dit toegangsniveau in Java geen expliciete naam heeft en alleen wordt bereikt wanneer alle andere toegangwijzigingsopties worden weggelaten. Het attribuut
internal
is beschikbaar in ActionScript 3.0 zodat u expliciet kunt proberen een eigenschap alleen zichtbaar te maken voor aanroepers binnen zijn eigen pakket.
Het attribuut static
Met het attribuut
static
, dat kan worden gebruikt met de eigenschappen die zijn gedeclareerd met het trefwoord
var
,
const
of
function
, kunt u een eigenschap aan een klasse koppelen in plaats van aan de instantie van een klasse. Code die zich niet in de klasse bevindt, moet eigenschappen van het type static met de klassenaam in plaats van de instantienaam aanroepen.
Eigenschappen van het type static worden niet door subklassen overgeërfd, maar zijn deel van de bereikketen van de subklasse. Dit houdt in dat er in de hoofdtekst van een subklasse een variabele of methode van het type static kan worden gebruikt, zonder dat verwezen hoeft te worden naar de klasse waarin deze is gedefinieerd.
Door de gebruiker gedefinieerde naamruimte-attributen
Als alternatief voor de vooraf gedefinieerde attributen voor toegangsbeheer kunt u een aangepaste naamruimte maken die u als attribuut gebruikt. Er kan slechts één naamruimte-attribuut per definitie worden gebruikt en u kunt niet een naamruimte-attribuut in combinatie met een van de attributen voor toegangsbeheer (
public
,
private
,
protected
,
internal
) gebruiken.
Variabelen
Variabelen kunnen met de trefwoorden
var
of
const
worden gedeclareerd. De waarde van een variabele die wordt gedeclareerd met het trefwoord
var
, kan meerdere keren wijzigen tijdens het uitvoeren van het script. Variabelen die zijn gedeclareerd met het trefwoord
const
, zijn
constanten
en ze kunnen slechts eenmaal waarden toegewezen krijgen. Als u een nieuwe waarde aan een geïnitialiseerde constante probeert toe te wijzen, wordt een fout gegenereerd.
Variabelen van het type static
Variabelen van het type static worden gedeclareerd met gebruik van het trefwoord
static
en de instructie
var
of
const
. Variabelen van het type static, die aan een klasse zijn gekoppeld in plaats van aan een instantie van een klasse, zijn nuttig voor het opslaan en delen van informatie die van toepassing is op de gehele klasse van objecten. Een variabele van het type static is bijvoorbeeld nuttig als u het aantal keer dat een klasse wordt geïnstantieerd, wilt bijhouden of als u het maximale aantal toegestane klasseninstanties wilt opslaan.
Het volgende voorbeeld maakt een variabele
totalCount
om het aantal instanties van een klasse bij te houden en een constante
MAX_NUM
om het maximale aantal instanties op te slaan. De variabelen
totalCount
en
MAX_NUM
zijn statisch omdat ze alleen waarden bevatten die van toepassing zijn op de klasse als een geheel en niet op een bepaalde instantie.
class StaticVars
{
public static var totalCount:int = 0;
public static const MAX_NUM:uint = 16;
}
Code die zich niet in de klasse StaticVars en een van zijn subklassen bevindt, kan alleen via de klasse zelf naar de eigenschappen
totalCount
en
MAX_NUM
verwijzen. De volgende code werkt bijvoorbeeld als volgt:
trace(StaticVars.totalCount); // output: 0
trace(StaticVars.MAX_NUM); // output: 16
U hebt via de instantie van de klasse geen toegang tot variabelen van het type static, daarom retourneert de code hieronder de volgende fout:
var myStaticVars:StaticVars = new StaticVars();
trace(myStaticVars.totalCount); // error
trace(myStaticVars.MAX_NUM); // error
Variabelen die worden gedeclareerd met de trefwoorden
static
en
const
, moeten op hetzelfde moment worden geïnitialiseerd als dat de constante wordt gedeclareerd, zoals de klasse StaticVars dit ook doet voor
MAX_NUM
. U kunt binnen de constructor of een instantiemethode geen waarde toewijzen aan
MAX_NUM
. De volgende code genereert een fout, omdat dit geen geldige manier is om een statische constante te initialiseren:
// !! Error to initialize static constant this way
class StaticVars2
{
public static const UNIQUESORT:uint;
function initializeStatic():void
{
UNIQUESORT = 16;
}
}
Instantievariabelen
Instantievariabelen bevatten eigenschappen die zijn gedeclareerd met het trefwoord
var
en
const
, maar zonder het trefwoord
static
. Instantievariabelen, die aan klasseninstanties zijn gekoppeld in plaats van aan een gehele klasse, zijn nuttig voor het opslaan van waarden die specifiek zijn voor een instantie. De klasse Array bevat bijvoorbeeld een instantie-eigenschap met de naam
length
die het aantal arrayelementen opslaat dat een bepaalde instantie van een klasse Array bevat.
Instantievariabelen, ongeacht of ze zijn gedeclareerd als
var
of
const
, kunnen niet worden overschreven in een subklasse. Door de methode getter en setter te overschrijven kunt u echter een vergelijkbaar resultaat behalen.
Methoden
Methoden zijn functies die deel zijn van een klassendefinitie. Wanneer een instantie van de klasse is gemaakt, wordt een methode aan die instantie gekoppeld. In tegenstelling tot een functie die buiten een klasse wordt gedeclareerd, kan een methode niet worden gebruikt zonder de instantie waaraan deze is gekoppeld.
Methoden worden gedefinieerd met het trefwoord
function
. Zoals bij elke klasseneigenschap, kunt u een van de attributen van klasseneigenschap toepassen op methoden, zoals private, protected, public, internal, static of een aangepaste naamruimte. U kunt een instructie function gebruiken, zoals:
public function sampleFunction():String {}
U kunt ook een variabele gebruiken waaraan u een functie-expressie toewijst:
public var sampleFunction:Function = function () {}
In de meeste gevallen zult u de instructie function gebruiken in plaats van een functie-expressie, dit vanwege de volgende redenen:
-
Instructies function zijn beknopter en eenvoudiger te lezen.
-
Met instructies function kunt u de trefwoorden
override
en
final
gebruiken.
-
Instructies function zorgen voor een sterkere band tussen de id, de naam van de functie en de code in de hoofdtekst van de methode. Omdat de waarde van een variabele met een toewijzingsinstructie kan worden gewijzigd, kan de verbinding tussen een variabele en zijn functie-expressie op elk moment worden verbroken. Hoewel u dit probleem kunt vermijden door de variabele te declareren met
const
in plaats van
var
, wordt deze techniek niet aangeraden, omdat het de code moeilijk te lezen maakt en dit het gebruik van de trefwoorden
override
en
final
verhindert.
Een van de gevallen waarin u een functie-expressie moet gebruiken, is wanneer u een functie aan het prototypeobject wilt koppelen.
Constructormethoden
Constructormethoden, oftewel
constructors
, zijn functies die de naam van de klasse delen waarin ze zijn gedefinieerd. Elke code die u in een constructormethode opneemt, wordt uitgevoerd wanneer een instantie van de klasse wordt gemaakt met het trefwoord
new
. De volgende code definieert bijvoorbeeld een eenvoudige klasse met de naam Example, die een enkele eigenschap met de naam
status
bevat. De oorspronkelijke waarde van de variabele
status
wordt binnen de constructorfunctie ingesteld.
class Example
{
public var status:String;
public function Example()
{
status = "initialized";
}
}
var myExample:Example = new Example();
trace(myExample.status); // output: initialized
Constructormethoden kunnen alleen public zijn, maar het gebruik van het attribuut
public
is optioneel. U kunt geen van de andere toegangsbeheerspecificaties gebruiken, ook niet
private
,
protected
of
internal
voor een constructor. U kunt ook geen door de gebruiker gedefinieerde naamruimte gebruiken met een constructormethode.
Een constructor kan een expliciete aanroep naar de constructor of naar een van zijn directe superklassen maken met de instructie
super()
. Als de constructor van superklassen niet expliciet wordt aangeroepen, voegt de compiler automatisch een aanroep in voor de eerste instructie in de constructorhoofdtekst. U kunt methoden van de superklasse ook aanroepen met het voorvoegsel
super
als een verwijzing naar de superklasse. Als u besluit om zowel
super()
als
super
in dezelfde constructorhoofdtekst te gebruiken, moet u zorgen dat u eerst
super()
aanroept. Anders gedraagt de verwijzing
super
zich niet als verwacht. De constructor
super()
moet ook worden aangeroepen voor een instructie
throw
of
return
.
Het volgende voorbeeld demonstreert wat er gebeurt als u de verwijzing
super
probeert te gebruiken voordat u de constructor
super()
aanroept. Een nieuwe klasse, ExampleEx, breidt de klasse Example uit. De constructor ExampleEx probeert toegang te krijgen tot de variabele status die in zijn superklasse is gedefinieerd, maar doet dit voordat deze
super()
aanroept. De instructie
trace()
binnen de constructor ExampleEx produceert de waarde
null
omdat de variabele
status
niet beschikbaar is totdat de constructor
super()
wordt uitgevoerd.
class ExampleEx extends Example
{
public function ExampleEx()
{
trace(super.status);
super();
}
}
var mySample:ExampleEx = new ExampleEx(); // output: null
Hoewel u de instructie
return
binnen een constructor kunt gebruiken, is het niet toegestaan een waarde te retourneren. Met andere woorden, de instructie
return
moet geen gekoppelde expressies of waarden hebben. Constructormethoden kunnen dan ook geen waarden retourneren, wat inhoudt dat er geen retourneringstype mag worden opgegeven.
Als u geen constructormethode in uw klasse definieert, maakt de compiler automatisch een lege constructor. Als uw klasse een andere klasse uitbreidt, voegt de compiler een aanroep
super()
toe aan de constructor die door het programma wordt gemaakt.
Methoden van het type static
Statische methoden, oftewel
klassenmethoden
, zijn methoden die met het trefwoord
static
zijn gedeclareerd. Statische methoden, die aan een klasse zijn gekoppeld in plaats van aan de instantie van een klasse, zijn nuttig voor het inkapselen van functies die effect hebben op iets anders dan de status van een individuele instantie. Omdat statische methoden als een geheel aan een klasse zijn gekoppeld, hebt u alleen via een klasse toegang tot statische methoden en niet via de instantie van een klasse.
Statische methoden zijn nuttig voor het inkapselen van functies die niet beperkt zijn tot het beïnvloeden van de status van klasseninstanties. Met andere woorden, een methode zou statisch moeten zijn als deze functies biedt die niet direct effect hebben op de waarde van een klasseninstantie. De klasse Date bevat bijvoorbeeld een statische methode met de naam
parse()
, die een tekenreeks gebruikt en het in een getal omzet. De methode is statisch, omdat deze geen effect heeft op een individuele instantie van de klasse. In plaats hiervan gebruikt de methode
parse()
een tekenreeks die een datumwaarde vertegenwoordigt, parseert deze tekenreeks en retourneert een getal met een indeling die compatibel is met de interne representatie van een object Date. Deze methode is geen instantiemethode, omdat het geen nut heeft om de methode op een instantie van de klasse Date toe te passen.
Vergelijk de statische methode
parse()
met een van de instantiemethoden van de klasse Date, zoals
getMonth()
. De methode
getMonth()
is een instantiemethode, omdat deze direct met de waarde van een instantie werkt door een bepaald component, de maand, van een instantie Date op te halen.
Omdat statische methoden niet gekoppeld zijn aan individuele instanties, kunt u de trefwoorden
this
en
super
niet binnen de hoofdtekst van een statische methode gebruiken. Zowel de verwijzing
this
als
super
zijn alleen nuttig binnen de context van een instantiemethode.
In tegenstelling tot sommige op klassen gebaseerde programmeertalen worden statische methoden in ActionScript 3.0 niet overgeërfd.
Instantiemethoden
Instantiemethoden zijn methoden die zijn gedeclareerd zonder het trefwoord
static
. Instantiemethoden, die aan instanties van een klasse zijn gekoppeld in plaats van aan een klasse zelf, zijn nuttig voor het implementeren van functionaliteit die individuele instanties van een klasse beïnvloedt. De klasse Array bevat bijvoorbeeld een instantiemethode met de naam
sort()
, die rechtstreeks met instanties Array werkt.
In de hoofdtekst van een instantiemethode zijn zowel statische als instantievariabelen bereikbaar. Dit houdt in dat met een eenvoudige id naar variabelen kan worden verwezen die in dezelfde klasse zijn gedefinieerd. De volgende klasse, CustomArray, breidt bijvoorbeeld de klasse Array uit. De klasse CustomArray definieert een statische variabele met de naam
arrayCountTotal
om het totale aantal klasseninstanties bij te houden, een instantievariabele met de naam
arrayNumber
om de volgorde bij te houden waarin de instanties zijn gemaakt en een instantiemethode met de naam
getPosition()
die de waarden van deze variabelen retourneert.
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);
}
}
Hoewel code buiten de klasse naar de statische variabele
arrayCountTotal
moet via het klassenobject toegang krijgen met gebruik van
CustomArray.arrayCountTotal
, kan code in de hoofdtekst van de methode
getPosition()
direct naar de statische variabele
arrayCountTotal
verwijzen. Dit geldt ook voor statische variabelen in superklassen. Statische eigenschappen worden in ActionScript 3.0 niet overgeërfd, maar statische eigenschappen in superklassen liggen in het bereik. De klasse Array heeft bijvoorbeeld enkele statische variabelen, waarvan één een constante is met de naam
DESCENDING
. Code in een subklasse Array kan toegang hebben tot de statische constante
DESCENDING
met een eenvoudige id:
public class CustomArray extends Array
{
public function testStatic():void
{
trace(DESCENDING); // output: 2
}
}
De waarde van de verwijzing
this
in de hoofdtekst van een instantiemethode is een verwijzing naar de instantie waaraan de methode is gekoppeld. De volgende code demonstreert dat de verwijzing
this
naar de instantie verwijst die de methode bevat:
class ThisTest
{
function thisValue():ThisTest
{
return this;
}
}
var myTest:ThisTest = new ThisTest();
trace(myTest.thisValue() == myTest); // output: true
Overerving van instantiemethoden kan worden beheerd met de trefwoorden
override
en
final
. U kunt het attribuut
override
gebruiken om een overgeërfde methode opnieuw te definiëren, en het attribuut
final
gebruiken om te voorkomen dat subklassen een methode overschrijven.
Accessormethoden get en set
Met de accessorfuncties get en set, ook bekend als
getters
en
setters
, kunt u voldoen aan de programmeerprincipes voor het verbergen van informatie en inkapseling en beschikt u over een eenvoudig te gebruiken programmeerinterface voor de klassen die u maakt. Met de functies get en set kunt u klasseneigenschappen als private instellen voor de klasse, maar kunnen gebruikers van de klasse deze eigenschappen wel benaderen alsof zij een klassenvariabele benaderen in plaats van een klassenmethode aan te roepen.
Het voordeel van deze aanpak is dat u hiermee het gebruik van traditionele accessorfuncties met onpraktische namen kunt vermijden, zoals
getPropertyName()
en
setPropertyName()
. Een ander voordeel van getters en setters is dat u het gebruik kunt vermijden van twee publieksgerichte functies voor elke eigenschap waarmee u lees- en schrijftoegang toestaat.
De volgende voorbeeldklasse, GetSet genaamd, bevat accessorfuncties get en set met de naam
publicAccess()
die toegang bieden tot een variabele van het type private met de naam
privateProperty
:
class GetSet
{
private var privateProperty:String;
public function get publicAccess():String
{
return privateProperty;
}
public function set publicAccess(setValue:String):void
{
privateProperty = setValue;
}
}
Als u probeert direct toegang te krijgen tot de eigenschap
privateProperty
, treedt een fout op; dit wordt aan de hand van het volgende voorbeeld getoond:
var myGetSet:GetSet = new GetSet();
trace(myGetSet.privateProperty); // error occurs
In plaats hiervan maakt de gebruiker van de klasse GetSet gebruik van iets dat vergelijkbaar is met de eigenschap met de naam
publicAccess
, maar dat eigenlijk een paar accessorfuncties get en set is die werken met de eigenschap van het type private met de naam
privateProperty
. Het volgende voorbeeld instantieert de klasse GetSet en stelt vervolgens de waarde van
privateProperty
in met de accessor van het type public met de naam
publicAccess
:
var myGetSet:GetSet = new GetSet();
trace(myGetSet.publicAccess); // output: null
myGetSet.publicAccess = "hello";
trace(myGetSet.publicAccess); // output: hello
Functies getter en setter maken het ook mogelijk eigenschappen te overschrijven die zijn overgeërfd van een superklasse; dit is niet mogelijk wanneer u standaardklassenlidvariabelen gebruikt. Klassenlidvariabelen die zijn gedeclareerd met het trefwoord
var
, kunnen in een subklasse niet worden overschreven. Eigenschappen die zijn gemaakt met functies getter en setter, hebben deze beperking echter niet. U kunt het attribuut
override
gebruiken voor functies getter en setter die van een superklasse zijn overgeërfd.
Gebonden methoden
Een gebonden methode, ook bekend als een
methode closure
, is een methode die is opgehaald uit zijn instantie. Voorbeelden van gebonden methoden zijn methoden die als argumenten aan een functie zijn doorgegeven of zijn geretourneerd als waarden van een functie. Gebonden methoden zijn nieuw in ActionScript 3.0 en zijn vergelijkbaar met een functie closure door het feit dat deze zelfs na het ophalen uit zijn instantie zijn lexicale omgeving behoudt. Het belangrijkste verschil tussen een gebonden methode en een functie closure is dat de verwijzing
this
van een gebonden methode gekoppeld (gebonden) blijft aan de instantie die de methode implementeert. Met andere woorden, de verwijzing
this
verwijst in een gebonden methode altijd naar het oorspronkelijke object dat de methode heeft geïmplementeerd. Voor functies closure is de verwijzing
this
algemeen; dit houdt in dat de functie verwijst naar een object waaraan de functie is gekoppeld op het moment dat deze wordt aangeroepen.
Het is belangrijk dat u de werking van gebonden methoden begrijpt als u het trefwoord
this
gebruikt. Het trefwoord
this
biedt een verwijzing naar het bovenliggende object van een methode. De meeste ActionScript-programmeurs verwachten dat het trefwoord
this
altijd het object of de klasse vertegenwoordigt die de definitie van een methode bevat. Zonder het binden van methoden is dit echter niet altijd waar. In vorige versies van ActionScript verwees het gereserveerde woord
this
bijvoorbeeld niet altijd naar de instantie die de methode heeft geïmplementeerd. Wanneer methoden uit een instantie in ActionScript 2.0 worden opgehaald, is de verwijzing
this
niet alleen aan de oorspronkelijk instantie gebonden, maar zijn ook de lidvariabelen en methoden van de klasse van de instantie niet beschikbaar. Dit vormt geen probleem in ActionScript 3.0, omdat gebonden methoden automatisch worden gemaakt wanneer u een methode als een parameter doorgeeft. Gebonden methoden zorgen ervoor dat het trefwoord
this
altijd naar het object of de klasse verwijst waarin een methode is gedefinieerd.
De volgende code definieert een klasse met de naam ThisTest; de klasse bevat een methode met de naam
foo()
die de gebonden methode definieert en een methode met de naam
bar()
die de gebonden methode retourneert. Externe klassencode maakt een instantie van de klasse ThisTest, roept de methode
bar()
aan en slaat de geretourneerde waarde in een variabele op met de naam
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 */
De laatste twee coderegels laten zien dat de verwijzing
this
in de gebonden methode
foo()
nog steeds naar een instantie van de klasse ThisTest verwijst, zelfs nadat de verwijzing
this
in de regel hiervoor naar het algemene object verwijst. Bovendien heeft de gebonden methode die is opgeslagen in de variabele
myFunc
, nog steeds toegang tot de lidvariabelen van de klasse ThisTest. Als dezelfde code in ActionScript 2.0 wordt uitgevoerd, zouden de verwijzingen
this
overeenkomen en zou de variabele
num
undefined
zijn.
De toegevoegde waarde van gebonden methoden is vooral merkbaar bij het gebruik van gebeurtenishandlers, omdat voor de methode
addEventListener()
is vereist dat u een functie of methode als argument doorgeeft.
Opsommingen met klassen
Opsommingen
zijn aangepaste gegevenstypen die u maakt om een kleine set waarden in te kapselen. ActionScript 3.0 ondersteunt geen specifieke opsomfaciliteit, dit in tegenstelling met C++ die het trefwoord
enum
kent of Java met een opsommingsinterface. U kunt opsommingen echter maken met klassen en statische constanten. De klasse PrintJob in ActionScript 3.0 gebruikt bijvoorbeeld een opsomming met de naam PrintJobOrientation om de waarden
"landscape"
(liggend) en
"portrait"
(staand) op te slaan, zoals geïllustreerd in de volgende code:
public final class PrintJobOrientation
{
public static const LANDSCAPE:String = "landscape";
public static const PORTRAIT:String = "portrait";
}
Normaal gesproken wordt een opsommingsklasse gedeclareerd met het attribuut
final
, omdat het niet nodig is de klasse uit te breiden. De klasse bestaat alleen uit leden van het type static; dit houdt in dat u geen instanties van de klasse hoeft te maken. In plaats hiervan hebt u via het klassenobject direct toegang tot de waarde van de opsomming, zoals getoond in het volgende codefragment:
var pj:PrintJob = new PrintJob();
if(pj.start())
{
if (pj.orientation == PrintJobOrientation.PORTRAIT)
{
...
}
...
}
Elk van de opsommingsklassen in ActionScript 3.0 bevat alleen variabelen van het type String, int of uint. Het voordeel van het gebruik van opsommingen in plaats van een letterlijke tekenreeks of getalwaarden is dat typografische fouten eenvoudiger op te sporen zijn. Als u de naam van een opsomming fout spelt, genereert de ActionScript-compiler een fout. Als u letterlijke waarden gebruikt, genereert de compiler geen fout als u een woord onjuist spelt of een fout getal gebruikt. In het vorige voorbeeld genereert de compiler een fout als de naam van de constante in de opsomming onjuist is, zoals getoond door het volgende fragment:
if (pj.orientation == PrintJobOrientation.PORTRAI) // compiler error
De compiler genereert echter geen fout als u een letterlijke tekenreekswaarde fout spelt:
if (pj.orientation == "portrai") // no compiler error
Een tweede manier waarop u opsommingen kunt maken, is met een afzonderlijke klasse met statische eigenschappen voor de opsomming. Deze techniek verschilt echter in het feit dat elk van de statische eigenschappen een instantie van de klasse bevat in plaats van een tekenreeks of een geheel getal. De volgende code maakt bijvoorbeeld een opsommingsklasse voor de dagen van de week:
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();
}
Deze techniek wordt niet door ActionScript 3.0 gebruikt, maar door veel ontwikkelaars die de verbeterde typecontrole die de techniek biedt willen benutten. Een methode die bijvoorbeeld een opsommingswaarde retourneert, kan de geretourneerde waarde beperken tot het gegevenstype van de opsomming. De volgende code toont niet alleen een functie die een weekdag retourneert, maar ook een functieaanroep die het opsommingstype gebruikt als een typeannotatie:
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();
U kunt de klasse Day ook op een dergelijke manier verbeteren dat deze een geheel getal aan elke dag van de week koppelt en een methode
toString()
biedt die een tekenreeksrepresentatie van de dag retourneert.
Ingesloten klassenelementen
ActionScript 3.0 gebruikt special klassen,
ingesloten klassenelementen
genoemd, om ingesloten elementen te vertegenwoordigen. Een
ingesloten element
is een element, zoals een geluid, afbeelding of lettertype dat bij uitvoering in een SWF-bestand is opgenomen. Als u een element insluit in plaats van het dynamisch te laden, zorgt u ervoor dat het bij uitvoering beschikbaar is; dit gaat echter ten koste van een verhoogde SWF-bestandsgrootte.
Ingesloten klassenelementen in Flash Professional gebruiken
Als u een element wilt insluiten, plaatst u het element eerst in de bibliotheek van een FLA-bestand. Gebruik vervolgens de koppelingseigenschap van het element om een naam op te geven voor het ingesloten klassenelement van het element. Als er geen klasse met die naam in het klassenpad kan worden gevonden, wordt er automatisch een klasse voor u gegenereerd. U kunt vervolgens een instantie van het ingesloten klassenelement maken en eigenschappen en methoden gebruiken die door die klasse zijn gedefinieerd of overgeërfd. De volgende code kan bijvoorbeeld worden gebruikt om een ingesloten geluid af te spelen dat is gekoppeld aan een ingesloten klassenelement met de naam PianoMusic:
var piano:PianoMusic = new PianoMusic();
var sndChannel:SoundChannel = piano.play();
U kunt ook de metagegevenstag
[Embed]
gebruiken om middelen in een Flash Professional-project in te sluiten, zoals beschreven in de volgende sectie. Als u de metagegevenstag
[Embed]
in uw code gebruikt, gebruikt Flash Professional in plaats van de Flash Professional-compiler de Flex-compiler om uw project te compileren.
Met de ingesloten klassen van middelen met de Flex-compiler.
Om een middel in een ActionScript-code in te sluiten, als u uw code compileert met de Flex-compiler, gebruikt u de metagegevenstag
[Embed]
. Plaats het element in de hoofdbronmap of in een andere map die zich in het bouwpad van uw project bevindt. Wanneer de compiler van Flex een metagegevenstag Embed aantreft, wordt het ingesloten klassenelement automatisch gemaakt. U kunt toegang krijgen tot de klasse met behulp van een variabele van het gegevenstype Class dat u direct na de metagegevenstag
[Embed]
declareert. De volgende code sluit bijvoorbeeld een geluid met de naam geluid1.mp3 in en gebruikt een variabele met de naam
soundCls
om een verwijzing naar het ingesloten klassenelement op te slaan dat aan dat geluid is gekoppeld. In het voorbeeld wordt vervolgens een instantie van het ingesloten klassenelement gemaakt en de methode
play()
voor die instantie aangeroepen:
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
Als u de metagegevenstag
[Embed]
wilt gebruiken in een Flash Builder ActionScript-project, moet u eventueel noodzakelijke klassen uit het Flex-framework importeren. Als u bijvoorbeeld geluiden wilt insluiten, moet u de klasse mx.core.SoundAsset importeren. Als u het Flex-framework wilt gebruiken, neemt u het bestand framework.swc op in uw ActionScript-bouwpad. Daarmee wordt het SWF-bestand vergroot.
Adobe Flex
U kunt in Flex ook een element insluiten met de aanwijzing
@Embed()
in een MXML-tagdefinitie.
|
|
|