En klass är en abstrakt beteckning för ett objekt. I en klass lagras information om de typer av data som ett objekt kan innehålla och det beteende som objektet kan ärva. Fördelen med en sådan abstraktion kanske inte syns när du skriver små skript, som bara innehåller några få objekt som samverkar med varandra. Men efterhand som ett program utvecklas och växer ökar också antalet objekt som måste hanteras. I sådana fall blir det enklare att med hjälp av klasser styra hur objekt skapas och samverkar med varandra.
Så långt tillbaka som i ActionScript 1.0 kunde programmerarna använda Function-objekt för att skapa konstruktioner som liknade klasser. ActionScript 2.0 hade formellt stöd för klasser med nyckelord som
class
och
extends
. ActionScript 3.0 har fortsatt stöd för de nyckelord som introducerades i ActionScript 2.0, men innehåller också nya funktioner. ActionScript 3.0 innehåller till exempel förbättrad åtkomstkontroll via attributen
protected
och
internal
. Det ger också bättre kontroll över arv via nyckelorden
final
och
override
.
För utvecklare som har skapat klasser i programmeringsspråk som Java, C++ eller C# kommer ActionScript att kännas bekant. ActionScript delar många nyckelord och attributnamn, som
class
,
extends
och
public
, med de språken.
Obs!
I dokumentationen för Adobe ActionScript avser termen ”egenskap” alla medlemmar av ett objekt eller en klass, däribland variabler, konstanter och metoder. Termerna klass och statisk kan ofta användas som synonymer, men här är de olika. Termen klassegenskaper avser till exempel alla medlemmar i en klass, inte bara de statiska medlemmarna.
Klassdefinitioner
I ActionScript 3.0 används en syntax för klassdefinitioner som liknar den som används för klassdefinitioner i ActionScript 2.0. Korrekt syntax för en klassdefinition anropar nyckelordet
class
följt av klassnamnet. Klassbrödtexten, som omsluts av klammerparenteser (
{}
), följer efter klassnamnet. I följande kod skapas klassen Shape som innehåller en variabel som heter
visible
:
public class Shape
{
var visible:Boolean = true;
}
En viktig syntaxändring gäller klassdefinitioner som finns i ett paket. Om en klass finns i ett paket måste paketnamnet i ActionScript 2.0 inkluderas i klassdeklarationen. I ActionScript 3.0, som innehåller programsatsen
package
, måste paketnamnet inkluderas i paketdeklarationen i stället för i klassdeklarationen. I följande klassdeklarationer visas hur klassen BitmapData, som är en del av paketet flash.display, definieras i ActionScript 2.0 och i ActionScript 3.0:
// ActionScript 2.0
class flash.display.BitmapData {}
// ActionScript 3.0
package flash.display
{
public class BitmapData {}
}
Klassattribut
I ActionScript 3.0 kan du ändra klassdefinitionerna med något av dessa fyra attribut:
Attribut
|
Definition
|
dynamic
|
Egenskaper kan läggas till i förekomster vid körningen.
|
final
|
Får inte utökas av en annan klass.
|
internal
(standard)
|
Synligt för referenser inuti aktuellt paket.
|
public
|
Synligt för referenser överallt.
|
För alla dessa attribut, med undantag av
internal
, inkluderar du attributet explicit för att få det associerade beteendet. Om du till exempel inte inkluderar attributet
dynamic
när du definierar en klass kan du inte lägga till egenskaper i en klassinstans vid körning. Du tilldelar ett attribut genom att placera det i början av klassdefinitionen, vilket visas i följande kod:
dynamic class Shape {}
Observera att listan inte innehåller attributet
abstract
. Abstrakta klasser stöds inte i ActionScript 3.0. Observera också att listan inte innehåller attributen
private
och
protected
. Dessa attribut är bara betydelsefulla inuti en klassdefinition och kan inte tillämpas på själva klasserna. Om du vill att en klass inte ska vara synlig utanför ett paket placerar du klassen inuti paketet och markerar klassen med attributet
internal
. Du kan också utesluta attributen
internal
och
public
och då läggs attributet
internal
automatiskt till av kompilatorn. Du kan också definiera en klass som bara är synlig inuti den källfil i vilken den har definierats. Placera klassen längst ned i källfilen, nedanför paketdefinitionens avslutande klammerparentes.
Klassbrödtext
Klassbrödtexten omsluts av klammerparenteser. Den definierar klassens variabler, konstanter och metoder. I följande exempel visas deklarationen för klassen Accessibility i ActionScript 3.0:
public final class Accessibility
{
public static function get active():Boolean;
public static function updateProperties():void;
}
Du kan också definiera ett namnutrymme i en klassbrödtext. I följande exempel visas hur ett namnutrymme kan definieras i en klassbrödtext och användas som attribut för en metod i klassen:
public class SampleClass
{
public namespace sampleNamespace;
sampleNamespace function doSomething():void;
}
Med ActionScript 3.0 kan du inkludera definitioner men också programsatser i en klassbrödtext. Programsatser som finns inuti en klassbrödtext, men utanför en metoddefinition, körs en gång. Den här körningen sker när klassdefinitionen påträffas första gången och det associerade klassobjektet skapas. I följande exempel visas ett anrop till den externa funktionen
hello()
och en
trace
-programsats som matar ut ett bekräftelsemeddelande när klassen har definierats:
function hello():String
{
trace("hola");
}
class SampleClass
{
hello();
trace("class created");
}
// output when class is created
hola
class created
I ActionScript 3.0 kan du definiera en statisk egenskap och en instansegenskap med samma namn i samma klassbrödtext. I följande kod deklareras den statiska variabeln
message
och en förekomstvariabel med samma namn:
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
Klassegenskapsattribut
Vid beskrivning av ActionScript-objektmodellen betyder termen
egenskap
allt som kan vara medlem i en klass, däribland variabler, konstanter och metoder. I Referenshandbok för ActionScript 3.0 i Adobe Flash-plattformen används termen dock i en snävare betydelse. I det sammanhanget omfattar termen egenskap bara klassmedlemmar som är variabler eller som har definierats med en get- eller set-metod. I ActionScript 3.0 finns en serie attribut som kan användas med valfri klassegenskap. I följande tabell visas den här attributuppsättningen.
Attribut
|
Definition
|
internal
(standard)
|
Synligt för referenser inuti samma paket.
|
private
|
Synligt för referenser inuti samma klass.
|
protected
|
Synligt för referenser i samma klass och i härledda klasser.
|
public
|
Synligt för referenser överallt.
|
statiska
|
Anger att en egenskap tillhör klassen och inte förekomster av klassen.
|
UserDefinedNamespace
|
Anpassat namnutrymme som definierats av användaren.
|
Namnutrymmesattribut för åtkomstkontroll
I ActionScript 3.0 finns det fyra speciella attribut som styr åtkomsten till egenskaper som definierats inuti en klass:
public
,
private
,
protected
och
internal
.
Med attributet
public
blir en egenskap synlig överallt i skriptet. Om du vill att en metod ska vara tillgänglig för kod utanför paketet, måste du deklarera metoden med attributet
public
. Detta gäller för alla egenskaper, vare sig de deklarerats med nyckelordet
var
,
const
eller
function
.
Med attributet
private
blir en egenskap synlig bara för anropare i egenskapens definitionsklass. Detta skiljer sig från attributet
private
i ActionScript 2.0, som ger en underklass åtkomst till en privat egenskap i en superklass. En annan viktig skillnad gäller körningsåtkomst. I ActionScript 2.0 förhindrar nyckelordet
private
åtkomst bara vid kompileringen och kan lätt kringgås vid körningen. I ActionScript 3.0 gäller detta inte längre. Egenskaper som har markerats som
privata
är otillgängliga både vid kompilering och vid körning.
I följande kod skapas den enkla klassen PrivateExample med en privat variabel och därefter testas åtkomsten till den privata variabeln från klassens utsida.
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.
I ActionScript 3.0 skapar ett försök att få åtkomst till en privat egenskap med hjälp av punktoperatorn (
myExample.privVar
) ett kompileringsfel om du använder strikt läge. I annat fall rapporteras felet vid körningen, på samma sätt som när du använder egenskapsåtkomstoperatorn (
myExample["privVar"]
).
I följande tabell sammanfattas resultatet av åtkomstförsök till en privat egenskap som hör till en fast (och inte en dynamisk) klass:
|
Strikt läge
|
Standardläge
|
punktoperator (
.
)
|
kompileringsfel
|
körningsfel
|
hakparentesoperator (
[]
)
|
körningsfel
|
körningsfel
|
I klasser som deklarerats med attributet
dynamic
resulterar försök att komma åt en privat variabel inte i ett körningsfel. I stället är variabeln inte synlig, varför värdet
undefined
returneras. Ett kompileringsfel inträffar emellertid om du använder punktoperatorn i strikt läge. Följande exempel är detsamma som föregående exempel förutom att klassen PrivateExample deklarerats som en dynamisk klass:
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
Dynamiska klasser returnerar vanligtvis värdet
undefined
i stället för att generera ett fel när extern kod försöker komma åt en privat egenskap. I följande tabell visas att ett fel genereras bara när punktoperatorn används för att komma åt en privat egenskap i strikt läge:
|
Strikt läge
|
Standardläge
|
punktoperator (
.
)
|
kompileringsfel
|
undefined
|
hakparentesoperator (
[]
)
|
undefined
|
undefined
|
Attributet
protected
, som är nytt för ActionScript 3.0, gör att en egenskap blir synlig för anropare i dess egen klass eller i en underklass. En skyddad egenskap är därför tillgänglig i sin egen klass eller i klasser som ligger någonstans under den i arvshierarkin. Detta gäller oavsett om underklassen är i samma paket eller i ett annat paket.
Om du är bekant med ActionScript 2.0 ser du att den här funktionen påminner om attributet
private
i ActionScript 2.0. Attributet
protected
i ActionScript 3.0 liknar även attributet
protected
i Java. Skillnaden är att Java-versionen även tillåter åtkomst till anropare inom samma paket. Använd attributet
protected
när du har en variabel eller metod som underklasserna behöver men som du vill dölja för kod som ligger utanför arvskedjan.
Attributet
internal
, som är nytt för ActionScript 3.0, gör att en egenskap blir synlig för anropare i dess eget paket. Det här är standardattributet för kod inuti ett paket och det tillämpas på alla egenskaper som inte har något av följande attribut:
Attributet
internal
liknar standardåtkomstkontrollen i Java, men i Java finns det inget explicit namn för den här åtkomstnivån och den kan bara uppnås om man utesluter alla andra åtkomstmodifierare. Attributet
internal
är tillgängligt i ActionScript 3.0 för att du ska kunna bekräfta att du vill att en egenskap bara ska vara synlig för anropare i egenskapens eget paket.
static, attribut
Med attributet
static
, som du använder med egenskaper som deklarerats med nyckelorden
var
,
const
eller
function
, kan du bifoga en egenskap till klassen i stället för till förekomster av klassen. Kod som ligger utanför klassen måste anropa statiska egenskaper med hjälp av klassnamnet och inte med ett förekomstnamn.
Statiska egenskaper ärvs inte av underklasser, men egenskaperna är en del av underklassens omfångskedja. Detta betyder att en statisk variabel eller metod, i brödtexten till en underklass, kan användas utan att referera till klassen i vilken den har definierats.
Användardefinierade namnutrymmesattribut
Som ett alternativ till de fördefinierade åtkomstkontrollsattributen kan du skapa ett anpassat namnutrymme och använda det som ett attribut. Du kan bara använda ett namnutrymmesattribut per definition och du kan inte använda det i kombination med något av åtkomstkontrollsattributen (
public
,
private
,
protected
,
internal
).
Variabler
Du kan deklarera variabler med något av nyckelorden
var
eller
const
. Variabler som deklarerats med nyckelordet
var
kan få sina värden ändrade flera gånger under skriptkörningen. Variabler som deklarerats med nyckelordet
const
kallas
konstanter
och kan få värden bara en gång. Ett försök att tilldela en initierad konstant ett nytt värde resulterar i ett fel.
Statiska variabler
Statiska variabler deklareras med en kombination av nyckelordet
static
och någon av programsatserna
var
eller
const
. Använd statiska variabler, som bifogas till en klass i stället för till en förekomst av en klass, för att lagra och dela information som gäller en hel objektklass. En statisk variabel är lämplig om du vill hålla reda på hur många gånger en klass instansieras eller om du vill lagra maximalt tillåtet antal klassförekomster.
I följande exempel skapas variabeln
totalCount
som ska hålla reda på antalet klassinstansieringar och konstanten
MAX_NUM
som ska lagra maximalt tillåtet antal instansieringar. Variablerna
totalCount
och
MAX_NUM
är statiska eftersom de innehåller värden som tillämpas på klassen som helhet och inte på en viss förekomst.
class StaticVars
{
public static var totalCount:int = 0;
public static const MAX_NUM:uint = 16;
}
Kod som ligger utanför klassen StaticVars och dess underklasser kan referera till egenskaperna
totalCount
och
MAX_NUM
bara genom själva klassen. Följande kod fungerar till exempel:
trace(StaticVars.totalCount); // output: 0
trace(StaticVars.MAX_NUM); // output: 16
Du kan inte komma åt statiska variabler via en förekomst av klassen och följande kod returnerar ett fel:
var myStaticVars:StaticVars = new StaticVars();
trace(myStaticVars.totalCount); // error
trace(myStaticVars.MAX_NUM); // error
Variabler som har deklarerats med både nyckelordet
static
och
const
måste initieras samtidigt som du deklarerar konstanten, på samma sätt som klassen StaticVars gör för
MAX_NUM
. Du kan inte tilldela
MAX_NUM
ett värde inuti konstruktorn eller en förekomstmetod. Följande kod genererar ett fel, eftersom det inte är ett giltigt sätt att initiera en statisk konstant:
// !! Error to initialize static constant this way
class StaticVars2
{
public static const UNIQUESORT:uint;
function initializeStatic():void
{
UNIQUESORT = 16;
}
}
Förekomstvariabler
Förekomstvariabler innehåller egenskaper som deklarerats med nyckelorden
var
och
const
, men utan nyckelordet
static
. Använd förekomstvariabler, som bifogas till klassförekomster i stället för till en hel klass, när du vill lagra värden som är speciella för en förekomst. Klassen Array har till exempel en förekomstegenskap som heter
length
som lagrar det antal arrayelement som en viss förekomst av klassen Array innehåller.
Förekomstvariabler, vare sig de deklarerats som
var
eller
const
, får inte åsidosättas i en underklass. Du kan emellertid använda en funktion som liknar åsidosättning av variabler genom att åsidosätta get- och set-metoder.
Metoder
En metod är en funktion som är en del av en klassdefinition. När en förekomst av klassen har skapats binds en metod till denna förekomst. I motsats till en funktion som deklarerats utanför en klass, kan en metod inte användas utanför den förekomst som den är bifogad till.
Metoder definieras med hjälp av nyckelordet
function
. Precis som med klassegenskaper kan du också använda klassegenskapsattribut på metoder, bland annat privata, skyddade, offentliga, interna, statiska och anpassade namnutrymmen. Du kan använda en funktionssats som följande:
public function sampleFunction():String {}
Du kan också använda en variabel som du kopplar ett funktionsuttryck till så här:
public var sampleFunction:Function = function () {}
I de flesta fall använder du en funktionssats i stället för ett funktionsuttryck av följande skäl:
-
Funktionssatser är mer precisa och lättare att läsa.
-
Med funktionssatserna kan du använda nyckelorden
override
och
final
.
-
Funktionssatser skapar en starkare koppling mellan identifieraren (namnet på funktionen) och koden i metodbrödtexten. Eftersom värdet på en variabel kan ändras med en tilldelningssats kan kopplingen mellan en variabel och dess funktionsuttryck när som helst skadas. Även om du kan gå runt det här problemet genom att deklarera variabeln med
const
i stället för
var
är denna teknik inte att rekommendera. Koden blir svår att läsa och det går inte att använda nyckelorden
override
och
final
.
När du väljer att bifoga en funktion till prototypobjektet måste du använda ett funktionsuttryck.
Konstruktormetoder
Konstruktormetoder, som ibland kallas
konstruktorer
, är funktioner som har samma namn som den klass i vilken de har definierats. All kod som du inkluderar i en konstruktormetod körs när en förekomst av klassen skapas med nyckelordet
new
. I följande kod definieras en enkel klass som heter Example och som innehåller en enda egenskap som heter
status
. Det initiala värdet för variabeln
status
anges inuti konstruktorfunktionen.
class Example
{
public var status:String;
public function Example()
{
status = "initialized";
}
}
var myExample:Example = new Example();
trace(myExample.status); // output: initialized
Konstruktormetoder kan bara vara allmänna, men användningen av attributet
public
är valfri. Du kan inte använda någon av de andra åtkomstkontrollsspecifikationerna, däribland
private
,
protected
och
internal
, på en konstruktor. Du kan inte heller använda ett användardefinierat namnutrymme med en konstruktormetod.
En konstruktor kan anropa konstruktorn för sin direkta superklass med hjälp av programsatsen
super()
. Om superklasskonstruktorn inte explicit anropas infogar kompilatorn automatiskt ett anrop före den första programsatsen i konstruktorbrödtexten. Du kan också anropa superklassens metoder med hjälp av prefixet
super
som en referens till superklassen. Om du använder både
super()
och
super
i samma konstruktorbrödtext måste du först anropa
super()
. Annars beter referensen
super
sig på ett oväntat sätt. Konstruktorn
super()
måste också anropas före en
throw
- eller
return
-programsats.
I följande exempel visas vad som händer om du försöker använda referensen
super
innan du anropar konstruktorn
super()
. Den nya klassen ExampleEx utökar klassen Example. Konstruktorn ExampleEx försöker komma åt statusvariabeln som definierats i superklassen, men detta sker innan den anropar
super()
. Programsatsen
trace()
i konstruktorn ExampleEx skapar värdet
null
eftersom variabeln
status
inte är tillgänglig förrän konstruktorn
super()
körs.
class ExampleEx extends Example
{
public function ExampleEx()
{
trace(super.status);
super();
}
}
var mySample:ExampleEx = new ExampleEx(); // output: null
Även om det är tillåtet att använda programsatsen
return
inuti en konstruktor är det inte tillåtet att returnera ett värde.
return
-programsatser får alltså inte ha kopplade uttryck eller värden. Konstruktormetoder kan följaktligen inte ha returvärden, vilket betyder att ingen returtyp kan anges.
Om du inte definierar en konstruktormetod i klassen skapas en tom konstruktor automatiskt. Om klassen utökar en annan klass infogas ett
super()
-anrop i den konstruktor som genereras.
Statiska metoder
Statiska metoder, som också kallas
klassmetoder
, är metoder som deklareras med nyckelordet
static
. Använd statiska metoder, som bifogas till en klass och inte till en förekomst av en klass, när du kapslar in funktioner som påverkar något annat än en individuell förekomsts läge. Eftersom statiska metoder bifogas till en klass som en helhet, kan de bara nås via en klass och inte via en förekomst av klassen.
Använd statiska metoder för att kapsla in funktioner som inte begränsas till att påverka läget för en klassförekomst. En metod måste alltså vara statisk om den tillhandahåller funktioner som inte direkt påverkar värdet för en klassförekomst. Klassen Date har till exempel en statisk metod som heter
parse()
, som tar en sträng och konverterar den till ett tal. Metoden är statisk eftersom den inte påverkar en individuell förekomst av klassen. I stället tar metoden
parse()
en sträng som representerar ett datumvärde, tolkar strängen och returnerar ett tal i ett format som är kompatibelt med den interna representationen av ett Date-objekt. Metoden är inte en förekomstmetod eftersom det inte är lämpligt att använda metoden på en förekomst av klassen Date.
Jämför metoden
parse()
med en av förekomstmetoderna för klassen Date, till exempel
getMonth()
. Metoden
getMonth()
är en förekomstmetod eftersom den arbetar direkt på värdet för en förekomst genom att hämta en speciell komponent, månaden, för en Date-förekomst.
Eftersom statiska metoder inte är bundna till individuella förekomster, kan du inte använda nyckelorden
this
och
super
i brödtexten för en statisk metod. Referenserna
this
och
super
är bara meningsfulla i samband med en förekomstmetod.
Statiska metoder i ActionScript 3.0 ärvs inte till skillnad från vissa andra klassbaserade programmeringsspråk.
Förekomstmetoder
Förekomstmetoder är metoder som deklareras utan nyckelordet
static
. Du kan använda förekomstmetoder som bifogas till förekomster av en klass i stället för till klassen som helhet för att implementera funktioner som påverkar individuella förekomster av en klass. Klassen Array innehåller till exempel en förekomstmetod som heter
sort()
som arbetar direkt på Array-förekomster.
I en förekomstmetods brödtext finns både statiska variabler och förekomstvariabler i omfång, vilket betyder att variabler som definierats i samma klass kan refereras med en enkel identifierare. Klassen CustomArray utökar till exempel klassen Array. Klassen CustomArray definierar en statisk variabel som heter
arrayCountTotal
som spårar antalet klassförekomster, en förekomstvariabel som heter
arrayNumber
som spårar den ordning i vilken förekomsterna skapats samt en förekomstmetod som heter
getPosition()
som returnerar värdena för dessa variabler.
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);
}
}
Även om kod som ligger utanför klassen måste komma åt den statiska variabeln
arrayCountTotal
via klassobjektet med hjälp av
CustomArray.arrayCountTotal
, så kan kod som ligger i brödtexten för metoden
getPosition()
referera direkt till den statiska variabeln
arrayCountTotal
. Detta gäller även för statiska variabler i superklasser. Trots att statiska egenskaper inte ärvs i ActionScript 3.0, placeras statiska egenskaper i superklasser i omfång. Klassen Array har till exempel några få statiska variabler, varav en är en konstant som heter
DESCENDING
. Kod som finns i en Array-underklass kan komma åt den statiska konstanten
DESCENDING
med hjälp av en enkel identifierare:
public class CustomArray extends Array
{
public function testStatic():void
{
trace(DESCENDING); // output: 2
}
}
Värdet för referensen
this
i brödtexten för en förekomstmetod är en referens till förekomsten som metoden är bifogad till. I följande kod visas att referensen
this
pekar på förekomsten som innehåller metoden:
class ThisTest
{
function thisValue():ThisTest
{
return this;
}
}
var myTest:ThisTest = new ThisTest();
trace(myTest.thisValue() == myTest); // output: true
Arv av förekomstmetoder kan kontrolleras med nyckelorden
override
och
final
. Du kan använda attributet
override
för att omdefiniera en ärvd metod och attributet
final
för att förhindra att underklasser åsidosätter en metod.
Åtkomstmetoder med get och set
Med åtkomstfunktionerna get och set, som också kallas
get-
och
set-
metoder, kan du anpassa dig till programmeringsprinciperna för dold och kapslad information medan du samtidigt tillhandahåller ett enkelt programmeringsgränssnitt för de klasser du skapar. Med get- och set-metoderna blir klassegenskaperna privata för klassen, men användarna av klassen kan komma åt dessa egenskaper på samma sätt som om de kommer åt en klassvariabel i stället för att anropa en klassmetod.
Fördelen med detta är att du slipper de traditionella åtkomstfunktionerna med otympliga namn, till exempel
getPropertyName()
och
setPropertyName()
. En annan fördel med get och set är att du slipper ha två allmänna funktioner för varje egenskap som tillåter både läs- och skrivåtkomst.
Följande exempelklass GetSet innehåller get- och set-åtkomstfunktionerna som heter
publicAccess()
som ger åtkomst till den privata variabeln
privateProperty
:
class GetSet
{
private var privateProperty:String;
public function get publicAccess():String
{
return privateProperty;
}
public function set publicAccess(setValue:String):void
{
privateProperty = setValue;
}
}
Om du försöker komma åt egenskapen
privateProperty
direkt returneras ett fel:
var myGetSet:GetSet = new GetSet();
trace(myGetSet.privateProperty); // error occurs
I stället får användaren av klassen GetSet använda något som ser ut att vara egenskapen
publicAccess
, men som i själva verket är ett par get- och set-åtkomstfunktioner för den privata egenskapen
privateProperty
. I följande exempel instansieras klassen GetSet och här anges värdet för
privateProperty
med hjälp av den allmänna åtkomstfunktionen
publicAccess
:
var myGetSet:GetSet = new GetSet();
trace(myGetSet.publicAccess); // output: null
myGetSet.publicAccess = "hello";
trace(myGetSet.publicAccess); // output: hello
Med get- och set-funktionerna kan du också åsidosätta egenskaper som ärvs från en superklass, vilket inte är möjligt när du använder vanliga klassmedlemsvariabler. Klassmedlemsvariabler som deklarerats med nyckelordet
var
kan inte åsidosättas i en underklass. Egenskaper som har skapats med get- och set-funktioner har inte den här begränsningen. Du kan använda attributet
override
på get- och set-funktioner som ärvts från en superklass.
Bundna metoder
En bunden metod, som ibland kallas ett
metodslut
, är en metod som extraheras från sin förekomst. Bundna metoder är metoder som skickats som argument till en funktion eller som returnerats som värden från en funktion. Bundna metoder är en nyhet i ActionScript 3.0 och funktionen liknar ett funktionsslut på det sättet att den sparar sin lexikala miljö även när den extraheras från sin förekomst. Den största skillnaden mellan en bunden metod och ett funktionsslut är att referensen
this
för en bunden metod förblir länkad, eller bunden, till förekomsten som implementerar metoden. Referensen
this
i en bunden metod pekar alltså alltid på det ursprungliga objektet som implementerat metoden. När det gäller funktionsslut är referensen
this
generisk, vilket betyder att den pekar på det objekt som funktionen är kopplad till vid den tidpunkt den anropas.
Om du använder nyckelordet
this
måste du veta hur bundna metoder fungerar. Kom ihåg att nyckelordet
this
skapar en referens till en metods överordnade objekt. De flesta ActionScript-programmerare förväntar sig att nyckelordet
this
alltid representerar det objekt eller den klass som innehåller definitionen för en metod. Utan metodbindning stämmer det här inte alltid. I tidigare versioner av ActionScript refererar referensen
this
inte alltid till förekomsten som implementerat metoden. Om metoder extraheras från en förekomst i ActionScript 2.0 är referensen
this
inte bunden till ursprungsförekomsten och medlemsvariablerna och metoderna för förekomstens klass är dessutom inte tillgängliga. Detta är inget problem i ActionScript 3.0 eftersom bundna metoder automatiskt skapas när du skickar en metod som parameter. Med bundna metoder kommer nyckelordet
this
alltid att referera till det objekt eller den klass som en metod är definierad i.
I följande kod definieras klassen ThisTest som innehåller metoden
foo()
som definierar den bundna metoden, och metoden
bar()
som returnerar den bundna metoden. Kod som ligger utanför klassen skapar en förekomst av klassen ThisTest, anropar metoden
bar()
och lagrar returvärdet i variabeln
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 sista två kodraderna visar att referensen
this
i den bundna metoden
foo()
fortfarande pekar på en förekomst av klassen ThisTest, även om referensen
this
på raden före pekar på det globala objektet. Den bundna metoden som lagrats i variabeln
myFunc
har dessutom fortfarande åtkomst till medlemsvariablerna i klassen ThisTest. Om samma kod körs i ActionScript 2.0 kommer referensen
this
att matcha och variabeln
num
kommer att bli
undefined
.
Om du lägger till bundna metoder med händelsehanterare märks det mest eftersom metoden
addEventListener()
kräver att du skickar en funktion eller metod som ett argument.
Uppräkningar med klasser
Uppräkningar är anpassade datatyper som du skapar för att kapsla in en liten uppsättning värden.
I ActionScript 3.0 finns inte någon särskild uppräkningsfunktion i motsats till C++ som har nyckelordet
enum
och Java som har ett uppräkningsgränssnitt. Du kan emellertid skapa uppräkningar med hjälp av klasser och statiska konstanter. I klassen PrintJob i ActionScript 3.0 används till exempel en uppräkning som heter PrintJobOrientation för att spara värdena
"landscape"
och
"portrait"
, vilket visas i följande kod:
public final class PrintJobOrientation
{
public static const LANDSCAPE:String = "landscape";
public static const PORTRAIT:String = "portrait";
}
En uppräkningsklass deklareras med attributet
final
eftersom klassen inte behöver utökas. Klassen innehåller bara statiska medlemmar, vilket betyder att du inte skapar några instanser av klassen. I stället kommer du åt uppräkningsvärdena direkt via objektet class, vilket visas i följande kodutdrag:
var pj:PrintJob = new PrintJob();
if(pj.start())
{
if (pj.orientation == PrintJobOrientation.PORTRAIT)
{
...
}
...
}
Uppräkningsklasserna i ActionScript 3.0 innehåller bara variabler av typen String, int och uint. Fördelen med att använda uppräkningar i stället för litterala strängvärden eller talvärden är att det är lättare att hitta typografiska misstag med uppräkningar. Om du skriver namnet på en uppräkning fel genereras ett fel i ActionScript-kompilatorn. Om du använder litterala värden reagerar kompilatorn inte om du stavar ett ord fel eller använder fel tal. I föregående exempel genereras ett fel om namnet på uppräkningskonstanten är felaktigt, vilken visas i följande utdrag:
if (pj.orientation == PrintJobOrientation.PORTRAI) // compiler error
Inget fel genereras emellertid om du stavar fel på ett stränglitteralvärde:
if (pj.orientation == "portrai") // no compiler error
Ett annat sätt att skapa uppräkningar är att skapa en separat klass med statiska egenskaper för uppräkningen. Detta sätt är annorlunda på så sätt att varje statisk egenskap innehåller en förekomst av klassen i stället för en sträng eller ett heltal. Med följande kod skapas en uppräkningsklass för veckodagarna:
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();
}
Denna metod används inte i ActionScript 3.0 men används av många utvecklare som föredrar den förbättrade typkontroll som den här metoden ger. En metod som till exempel returnerar ett uppräkningsvärde kan begränsa returvärdet till uppräkningens datatyp. Med följande kod visas en funktion som returnerar en veckodag men också ett funktionsanrop som använder uppräkningstypen som en typanteckning.
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();
Du kan också utöka klassen Day så att den kopplar ett heltal till varje veckodag och som tillhandahåller en
toString()
-metod som returnerar ett strängbegrepp för dagen.
Inbäddade resursklasser
I ActionScript 3.0 används specialklasser, som även kallas
inbäddade resursklasser
, till att representera inbäddade resurser. En
inbäddad resurs
är en resurs, till exempel ett ljud, en bild eller ett teckensnitt, som ingår i en SWF-fil vid kompileringen. Om du bäddar in en resurs i stället för att läsa in den dynamiskt blir den tillgänglig vid körning, men SWF-filens storlek ökar då också.
Använda inbäddade resursklasser i Flash Professional
Om du vill bädda in en resurs placerar du först resursen i en FLA-fils bibliotek. Därefter använder du resursens länkningsegenskap för att ge resursens inbäddade klass ett namn. Om det inte finns någon klass med detta namn i klassökvägen genereras en klass automatiskt. Därefter kan du skapa en förekomst av den inbäddade resursklassen och använda alla egenskaperna och metoderna som definierats eller ärvts av denna klass. Följande kod kan till exempel användas för att spela upp ett inbäddat ljud som är länkat till en inbäddad resursklass som heter PianoMusic:
var piano:PianoMusic = new PianoMusic();
var sndChannel:SoundChannel = piano.play();
Du kan också använda metadatataggen
[Embed]
för att bädda in resurser i ett Flash Professional-projekt, vilket beskrivs nedan. Om du använder metadatataggen
[Embed]
i koden används Flex-kompilatorn för att kompilera projektet i stället för Flash Professional-kompilatorn.
Använda inbäddade resursklasser med Flex-kompilatorn
Om du kompilerar koden med Flex-kompilatorn och vill bädda in en resurs i ActionScript-koden använder du metadatataggen
[Embed]
. Placera resursen i huvudkällmappen eller i en annan mapp som finns i projektets byggsökväg. När Flex-kompilatorn påträffar en Embed-metadatatagg skapas den inbäddade resursklassen. Du får tillgång till klassen via en variabel av datatypen Class som du deklarerar omedelbart efter
[Embed]
-metadatataggen. I följande kod bäddas ett ljud med namnet sound1.mp3 in och en variabel med namnet
soundCls
används för att lagra en referens till den inbäddade resursklassen som hör till ljudet. I exemplet skapas sedan en förekomst av den inbäddade resursklassen och metoden
play()
anropas för den förekomsten:
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
Om du vill använda metadatataggen
[Embed]
i ett Flash Builder ActionScript-projekt importerar du de klasser som behövs från Flex-ramverket. Om du till exempel vill bädda in ljud importerar du klassen mx.core.SoundAsset. Om du vill använda Flex-ramverket inkluderar du filen framework.swc i ActionScript-byggsökvägen. Detta ökar storleken på SWF-filen.
Adobe Flex
I Flex kan du också bädda in en resurs med direktivet
@Embed()
i en MXML-taggdefinition.
|
|
|