Klasser
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.
KlassdefinitionerI 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 kräver 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 {}
}
KlassattributI ActionScript 3.0 kan du ändra klassdefinitionerna med något av dessa fyra attribut:
Attribut
|
Definition
|
dynamic
|
Egenskaper kan läggas till i instanser 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ödtextKlassbrö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 instansvariabel 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
KlassegenskapsattributVid 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 Adobe ActionScript 3.0 för 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.
|
static
|
Anger att en egenskap tillhör klassen och inte instanser av klassen.
|
UserDefinedNamespace
|
Anpassat namnutrymme som definierats av användaren.
|
Namnutrymmesattribut för åtkomstkontrollI 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, attributMed 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 instanser av klassen. Kod som ligger utanför klassen måste anropa statiska egenskaper med hjälp av klassnamnet och inte med ett instansnamn.
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 namnutrymmesattributSom 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).
VariablerDu 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 variablerStatiska 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 instans 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 klassinstanser.
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 instans.
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 instans 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 instansmetod. 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;
}
}
InstansvariablerInstansvariabler innehåller egenskaper som deklarerats med nyckelorden var och const, men utan nyckelordet static. Använd instansvariabler, som bifogas till klassinstanser i stället för till en hel klass, när du vill lagra värden som är speciella för en instans. Klassen Array har till exempel en instansegenskap som heter length som lagrar det antal arrayelement som en viss instans av klassen Array innehåller.
Instansvariabler, 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.
MetoderEn metod är en funktion som är en del av en klassdefinition. När en instans av klassen har skapats binds en metod till denna instans. I motsats till en funktion som deklarerats utanför en klass, kan en metod inte användas utanför den instans 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.
KonstruktormetoderKonstruktormetoder, 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 instans 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 metoderStatiska 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 instans av en klass, när du kapslar in funktioner som påverkar något annat än en individuell instans läge. Eftersom statiska metoder bifogas till en klass som en helhet, kan de bara nås via en klass och inte via en instans 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 klassinstans. En metod måste alltså vara statisk om den tillhandahåller funktioner som inte direkt påverkar värdet för en klassinstans. 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 instans 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 instansmetod eftersom det inte är lämpligt att använda metoden på en instans av klassen Date.
Jämför metoden parse() med en av instansmetoderna för klassen Date, till exempel getMonth(). Metoden getMonth() är en instansmetod eftersom den arbetar direkt på värdet för en instans genom att hämta en speciell komponent, månaden, för en Date-instans.
Eftersom statiska metoder inte är bundna till individuella instanser, 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 instansmetod.
Statiska metoder i ActionScript 3.0 ärvs inte till skillnad från vissa andra klassbaserade programmeringsspråk.
InstansmetoderInstansmetoder är metoder som deklareras utan nyckelordet static. Du kan använda instansmetoder som bifogas till instanser av en klass i stället för till klassen som helhet för att implementera funktioner som påverkar individuella instanser av en klass. Klassen Array innehåller till exempel en instansmetod som heter sort() som arbetar direkt på Array-instanser.
I en instansmetods brödtext finns både statiska variabler och instansvariabler 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 klassinstanser, en instansvariabel som heter arrayNumber som spårar den ordning i vilken instanserna skapats samt en instansmetod 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 instansmetod är en referens till instansen som metoden är bifogad till. I följande kod visas att referensen this pekar på instansen som innehåller metoden:
class ThisTest
{
function thisValue():ThisTest
{
return this;
}
}
var myTest:ThisTest = new ThisTest();
trace(myTest.thisValue() == myTest); // output: true
Arv av instansmetoder 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 setMed å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 metoderEn bunden metod, som ibland kallas ett metodslut, är en metod som extraheras från sin instans. 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 instans. 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 instansen 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 instansen som implementerat metoden. Om metoder extraheras från en instans i ActionScript 2.0 är referensen this inte bunden till ursprungsinstansen och medlemsvariablerna och metoderna för instansens 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 instans 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 instans 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 klasserUpprä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 literala 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 literala 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ängliteralvä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 instans 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 tillhandahåller en toString()-metod som returnerar en strängrepresentation för dagen.
Inbäddade resursklasserI 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 ProfessionalOm 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 instans 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-kompilatornOm 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 instans av den inbäddade resursklassen och metoden play() anropas för den instansen:
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 BuilderOm 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 FlexI Flex kan du också bädda in en resurs med direktivet @Embed() i en MXML-taggdefinition.
|
|