Macromedia Flash ActionScript 2.0 és ActionScript 3.0

Objektum-orientált programozás

1. Objektummodell - Osztálymodell

1. Dinamikus szemlélet

Mindenekelőtt tekintsük át, hogy az ActionScript hogyan is tekint az objektumokra, s azok osztályaira. Mint minden ismert objektum-orientált nyelvben, az AS-ben is az objektumokat úgy fogják fel, mint bizonyos tulajdonságokkal, és műveletekkel rendelkező dolgokat. Az egész elgondolás a mindennapi élet megfigyeléseinek analógiájára történt, ugyanis az emberi természet alapvetően osztályozó jellegű. Vagyis születésünktől fogva a körülöttünk lévő dolgokat megpróbáljuk valamiféle kategóriákba sorolni, s mint tudjuk, ezen kategóriák helyes megválasztása a társadalmi lét alappillére. Az első objektum-orientált nyelv tervezőinek szeme előtt is ez a példa állt, s így tűnik mindez annyira természetesnek. Az AS tervezői számos előre megírt olyan kategóriát építettek a nyelvbe, amelyekről úgy gondolták, hogy a mindennapi programozói életet megkönnyíthetik. (Igazuk is volt.). Az kategóriák vagyis az osztályok egy általános meghatározást jelentenek, minthogy az autók halmaza is egy ilyen általános fogalom, ám semmit nem mond az utca túlsó oldalán lévő Suzukiról. Az osztály mint „halmaz” egy-egy eleme az osztály egy példánya, vagyis egy objektum. Ez az objektum rendelkezik osztályának minden tulajdonságával, de ezeknek konkrét értéket is adhatunk. (Félreértés ne essék, az osztály egyes tulajdonságainak lehet általános értéke is.) Vagyis az autós példánál maradva, az autók osztályának egy tulajdonsága a szín, objektuma a Suzuki, aminek a színe a fehér. Lássuk, hogyan lehet objektumot létrehozni AS-ben:

	var varName:datatype = new ClassName();
ahol a varName az objektum neve, s általában a datatype (mint típus) meg kell, hogy egyezzen a ClassName-mel (vagyis az osztályunk nevével). Tehát új objektumot a „new” operátorral lehet létrehozni, amelyet az osztály konstruktorára alkalmazunk. Az így létrejött objektum tulajdonságaihoz kétfajta szintaxissal férhetünk hozzá:
	varName.prop1

	varName[prop1]
Míg egy metódust a következőképpen futtathatunk :
	varName.Method();
Mint ahogy már említettük, az AS beépített osztályokat is tartalmaz. Ezek azért is különleges osztályok, mert úgynevezett dinamikus osztályok, vagyis egy ilyen osztály objektumához készíthetünk az osztályban nem szereplő metódust, illetve tulajdonságot. Vagyis a következő kód teljesen helyes:
	var oDynamicObj:Object = new Object();
	oDynamicObj.dynamicProperty = “New property value”;

	oDynamicObj.dynamicMethod = function():Void {
		trace(“Method invoked”);
	};
	
Ezekre példaként tekintsük a következő kódot:
	function Circle(x, y, r)
	{
		this.x = x;
		this.y = y;
		this.r = r;
	}
  
	function moveRel(ox, oy)
	{
		this.x += ox;
		this.y += oy;
	}
  
	c = new Circle(2, 5, 4);
	c.moveRel(3, 5);
   
	c.visibility = true;
	delete c.visibility;
	
Így egy működési elvében nem szokványos, de használatában közel ismerős objektum modellt kaptunk a Flash-től.

2. Osztály alapú szemlélet

A dinamikus osztálymodellel szemben vezette be a JavaScript 2.0 után az ActionScript 3.0 is az osztály alapú szemléletet. Ebben a szemléletben leginkább a Java osztály felépítésére hasonlító elemeket vezettek be. Így lehetőséget adnak a programozónak szigorú típusosság használatára is. Osztályt és interface-t mindig külön ún. ActionScript(*.as) file-ban, amit ugyanúgy kell elnevezni, mint a definiált osztályt vagy interface-t. Az osztály nevére ugyanolyan szabályok érvényesek, mint a változókra, további konvenció, hogy nagybetűvel kezdődnek. Az osztályokat csomagokba kell foglalni, szintaktikailag másképpen kell jelölni, mint Javaban, de ugyanaz a csomag jelentése. Ha elkészültünk az osztállyal, akkor ugyanolyan rendszerben, mint ahogy Javaban a class file-okat helyeztük el, kell az ActionScript file-unkat elhelyezni a ClassPath-hez képest. Tehát itt is az osztályok egy rendszerezésének a lehetőségét adja a csomag rendszer.

package geometry {
	class Circle
	{
		private var x:Number, y:Number;
		private var r:Number;

		function Circle(x:Number, y:Number, r:Number)
		{
			this.x = x;
			this.y = y;
			this.r = r;
		}

		function moveRel(ox:Number, oy:Number):Void
		{
			x += ox;
			y += oy;
		}

		function toString():String
		{
			return "{x: "+x+", y: "+y", r: "+r"}"; 
		}
	}
}

	import Circle;
	var c:Circle = new Circle(100, 100, 50);
	c.moveRel(3, 5); 

Bevezeti az osztály (class) fogalmát, mely a szigorú típusosságra épít. Engedményként két lehetőséget hagynak, amivel a szigorú típusosságot ki lehet kerülni: az egyik, hogy osztályon belül lehet nem szigorúan típusos változó, a másik a dinamikus osztályok használatának a lehetősége. Ha egy osztályt dinamikusnak definiálunk, akkor ki lehet terjeszteni új mezőkkel.

Circle.as:

package shape {
	dynamic class Circle
	{
		private var x:Number, y:Number;
		private var r:Number;

		function Circle(x:Number, y:Number, r:Number)
		{
			this.x = x;
			this.y = y;
			this.r = r;
		}   
	}

	var circle:Circle = new Circle(100, 100, 50);
	circle.color = 0xAACC33; //itt nem lesz fordítási hiba mivel dynamic - nak deklaráltuk az osztályt, ellenkező esetben szólna a fordító
}

Osztályokon négy módosítótagot értelmez az AS3:

Hozzáférés szabályozásra két hozzáférési kategóriát vezettek be az AS2-ben: publikus (public) és privát (private), de a privát hozzáférési kategória inkább felelt meg egy védett hozzáférési kategóriának, mert a leszármazott osztályokban is látható volt a privát tag.
AS3-ban bevezették a protected és az internal névtereket is, sőt a régiek jelentése is megváltozott. A névterek és jelentésük tehát:

Ezeken kívül metódusokra még két módosító létezik:

Az osztályok privát adattagjaihoz szorosan kapcsolódik két, nem kötelezően, de ajánlottan definiálható függvény, a getter/setter függvények, nevükből adódóan az adattagok beállító, illetve lekérdező függvények. Az a konvenció, hogy a privát adattagokat „_” jellel kezdjük, épp innen ered, ugyanis a getter/setter függvényeket így logikusan lehet definiálni. Az ilyen függvényekre erősen rá akarnak szoktatni a fejlesztők, mivel egy-egy külön kulcsszót definiáltak számukra (get, set). Vagyis egy privát változó korrekt definiálása az osztályban a következőképp adódik:

	class Car {
		private var _make:String = null;

		public function get make():String {
			return _make;
		}
		public function set make(sMake:String):Void {
			_make = sMake;
		}
	}
	
Nem okoz problémát, hogy a getter/setter függvények ugyanolyan névvel vannak definiálva, a paraméterek különbözősége miatt.

Az AS lehetőséget biztosít statikus adattagok létrehozására a következőképpen:
static var STATIC_PROPERTY_NAME:Datatype = value;
Ezek akkor hasznosak, ha nem akarjuk, hogy az osztályunk példányaiban külön-külön szerepeljen ez a változó, csak az osztály fogja ezt tartalmazni. Mindez mintájára készíthetünk statikus metódusokat is:
static function methodName([paramList]):datatype { //utasítások }

Mivel az ilyen metódusokat is csak az osztály tartalmazza, nem használhat az utasításai közt privát, és public adattagokat, sem thist.

Saját objektum létrehozásához egy konstruktor műveletet lehet definiálni, aminek ugyanolyan nevet kell adni, mint amilyen típusú objektumot ő létre fog hozni. Konstruktorból csak egy lehet, és csakis public lehet. Természetesen a konstruktor függvényeknél is használható a törzsben a this kulcsszó. Mikor meghívunk egy konstruktort, akkor a Flash rejtett paraméterként átadja a thist. A konstruktor törzsben is lehet definiálni az objektum metódusait, bár ez nem ajánlott, mert így valahányszor meghívjuk a konstruktort, annyiszor lesz definiálva minden metódus.

Öröklő osztálynál a szülőosztály konstruktorát meghívhatjuk, ha a super() metódust meghívjuk, illetve a szülőosztály attribútumai és metódusai is elérhetőek, a super. prefixszel (pl. this.x = super.getX(); ).

	function Circle(radius)
	{
		this.radius = radius;
		this.getArea = function()
		{
			return Math.PI*this.radius*this.radius;
		};
		this.getDiameter = function()
		{
			return 2*this.radius;
		};
	}
	var myCircle = new Circle(55);
	trace(myCircle.getArea());
	trace(myCircle.getDiameter());
	

Felsorolási típusok ugyan nincsenek a nyelvben, de szimulálhatóak, ha egy final osztályba konstans static adattagokként felvesszük a lehetséges értékeket. Például:

public final class Colour {
	public static const BLACK:Number = 0x000000;
	public static const WHITE:Number = 0xFFFFFF;
}

Mivel minden függvény egy Function objektum, így minden függvény rendelkezik egy call() és egy apply() tagfüggvénnyel. Ha egy függvény törzsében azt szeretnénk, hogy a this máshova mutasson, akkor használhatjuk a call() utasítást. Például:

	myObject.myMethod(1, 2, 3);
	
De ha azt szeretnénk, hogy ebben a metódus törzsben a this cserélődjön le a myOtherObject - re:
	myObject.myMethod.call(myOtherObject, 1, 2, 3)
	
A null paraméter a megszokott hívást jelenti. Így a következő két utasítás ekvivalens:
	Math.sin(Math.PI / 4)
	Math.sin.call(null, Math.PI / 4)
	És egy utolsó szemléltető példa call() - ra:
	function myObject()
	{
		//empty
	}
	function myMethod(obj)
	{
		trace("this == obj? " + (this == obj));
	}
	var obj:Object = new myObject();
	myMethod.call(obj, obj); 
	//Az eredmény:
	this == obj? true 
	
Az apply() utasítással szintén helyettesíthetjük a thist a call()-hoz hasonlóan, és még meghatározhatjuk az átadandó paramétereket is, amit egy tömbbel tehetünk meg. Ez akkor nagyon hasznos, amikor az átadandó paraméterek száma nem ismert mindaddig, amíg a script végre nem hajtódik. Példa:

Az alábbi két utasítás ekvivalens:
	Math.atan2(1, 0)
	Math.atan2.apply(null, [1, 0]) 
	function theFunction()
	{
		trace(arguments);
	}
	// létrehozunk egy új tömböt, amit paraméterként átadunk az apply() - nak
	var firstArray:Array = new Array(1,2,3);
	theFunction.apply(null,firstArray);
	// Az eredmény: 1,2,3
	// létrehozunk egy második tömböt, amit paraméterként átadunk az apply() - nak
	var secondArray:Array = new Array("a", "b", "c");
	theFunction.apply(null,secondArray);
	// Az eredmény: a,b,c   

	
Itt is írhatunk a null helyett a call()-os utolsó példájához hasonlóan obj-t, és ellenőrizhetjük az egyenlőséget. Azaz:
	function theFunction()
	{
		trace("this == myObj? " + (this == myObj));
		trace("arguments: " + arguments);
	}
	var myObj:Object = new Object();
	var firstArray:Array = new Array(1,2,3);
	var secondArray:Array = new Array("a", "b", "c");
	theFunction.apply(myObj,firstArray);
	// Eredmény:
	// this == myObj? true
	// arguments: 1,2,3 
	theFunction.apply(myObj,secondArray);
	// Eredmény:
	// this == myObj? true
	// arguments: a,b,c 
	
Ha szeretnénk csökkenteni az swf fájlunk méretét, például úgy, hogy kihagyunk bizonyos osztályokat fordításkor, de ettől még hozzá szeretnénk férni ezekhez az osztályokhoz típusellenőrzés céljából, akkor erre az ActionScript a következő megoldást nyújtja: Hozzunk létre egy XML fájlt ugyanabban a könyvtrában, ahol az FLA fájlunk van. Az XML fájl neve legyen: FLA_filename_exclude.xml, ahol az FLA_filename az FLA osztály neve kiterjesztés nélkül. Az XML fájl felépítése:
	<excludeAssets>
	<asset name=" className1 "></asset>
	<asset name=" className2 "></asset>
	... 
	</excludeAssets> 
	
Így a className1 és className2 osztályok kimaradnak a fordításkor.

3. ActionScript 3.0

Az AS3 szemléletében egy osztály három dologból áll össze:

Tulajdonságok azok az adatok, amik összetartják az objektumokat, például egy Dal objektumnak van szerző illetve cím tulajdonsága, míg egy MovieClip objektumnak rotation, x, height, alpha tulajdonságai. Bizonyos szempontból gondolhatunk úgy a tulajdonságokra, mint az adott objektum alobjektumaira.

Tulajdonságokat a pont szintaxissal érhetünk el. Egy négyzet szélességére például így hivatkozhatunk:

square.width = 10;

A metódusok olyan műveletek, amit egy objektum tud elvégezni. Például egy MovieClip képes lejátszani magát a play() metódussal. A metódusok a tulajdonságokhoz hasonlóan érhetőek el.

Az események olyan valamik, amikről az ActionScript tud, és hatásukra valamely műveletet hajt végre. Az eseményeket az eseménykezelő vezérli.

Zárt osztályok

AS3-ban a legtöbb osztály zárt. Ez azt jelenti, hogy nem lehet hozzájuk adni dinamikus objektumokat példányosítás után. Ami eddig az osztályunkban szerepelt az benne is marad. Azonban nincs lehetőség például egy szám elhelyezésére az osztályban, hacsak nincs dinamikus-ként definiálva. Például ilyen dinamikus osztály a MovieClip, amin bármikor elhelyezhetünk változókat vagy függvényeket. Hogy egy osztály dinamikus vagy nem azt könnyen kideríthetjük az új kinézetű Súgó segítségével: megnézhetjük pl., hogy dinamikus osztály-e az Object. A class mellett ez áll: public dynamic class Object. Tehát dinamikus, így elhelyezhetünk rajta gond nélkül új változókat, s a fordító nem fog hibát dobni.

Namespace-ek

A namespace-ek deklarálásának lehetősége bizonyára ismerős azoknak, akik más, komolyabb programnyelvekkel dolgoznak. Pár namespace ismerős lesz: private, public, protected. Ezek a láthatóságért felelnek (lásd C++). Meghatározzák, hogy egy adott metódust, vagy változót honnan lehet elérni. Most már lehetőségünk van saját láthatóságot is definiálni, ami például megakadályozza a névütközést azonos nevű metódusok egy osztályon belüli deklarálása esetén, de akár xml kezelésnél is hasznosak lehetnek.

Az osztály objektum

Az általános objektum-orientált programozási paradigmában az osztályokat arra használjuk, hogy objektumok típusát definiáljuk velük. Azok a programozási nyelvek, amelyek ezt a paradigmát használják arra is hajlamosak, hogy az osztályokat arra használják, hogy olyan adattípusok példányait hozzák létre, amit az osztály maga definiált. Az ActionScript az osztályokat mind a két célra használja, de ehhez a prototípus alapúság egy érdekes karakterisztikát tesz hozzá. Az ActionScript minden osztály létrehozásakor készít egy speciális osztály objektumot, ami képes megosztani a viselkedést és az állapotokat is. Az ActionScript 3.0-t úgy tervezték meg, hogy kifinomult objektum-orientált ActionScript alkalmazást lehessen vele írni, anélkül hogy használná, vagy egészen megértené ezeknek az objektumoknak a működését a programozó. A haladó programozók számára, akik ki akarják használni ezeknek az osztály objektumoknak az előnyeit ennek fejezetnek a megvitatása lesz az ugrás a mélybe. A következő diagram azt mutatja, hogyan épül fel egy osztály objektum, ami az A osztályt reprezentálja és a class A {} utasítással definiáltuk:
Mi történik a háttérben, amikor egy osztályt definiálunk.
Az ábrán minden téglalap egy objektumot jelent. A diagramon minden objektumnak van az alsó indexében egy karakter. Az „A” azt jelképezi, hogy ő az A osztályhoz tartozik. Az osztály objektum (CA) referenciát tartalmaz számos más fontos objektumra. A példány jelleg objektuma (TA) tárolja a példány attribútumait, amit az osztály definíción belül hoztunk létre. Az osztály jelleg objektuma (TCA) jeleníti meg az osztály belső típusait, és az osztályban definiált statikus attribútumokat. A prototípus objektum (PA) mindig azonosítja azt az osztály objektumot, amihez eredetileg a konstruktorral lett hozzácsatolva.

A jelleg objektum

A jelleg objektum, egy új objektumtípus az ActionScript 3.0-ban. Ezt az objektumot a teljesítményt tartották szem előtt tartásával valósították meg. Az előző ActionScript verziókban, a nevek kikeresése időigényes folyamat volt, addig tartott, amíg a Flash Player végigment a prototípus láncon. ActionScript 3.0-ban, a nevek kikeresése sokkal hatékonyabb és gyorsabb lett, mert az öröklött attribútumokat lemásolódnak a leszármazott osztály jelleg objektumába. A jelleg objektum nem érhető el direkt módon a programkódból, de megléte látható a teljesítményjavulásban és a memóriahasználtban. A jelleg objektum információkat ad az osztály szerkezetről és tartalmáról az AVM2-nek. Ezen tudás birtokában az AVM2 képes a szembetűnően csökkenteni a futtatási időt, mert gyakran olyan direkt gépet generál, ami hozzáfér az attribútumokhoz, vagy metódusokat tud direkt meghívni anélkül, hogy az időigényes név keresést használná. Köszönhetően a jelleg objektumoknak az objektumok memória lenyomata sokkal kisebb, mint az előző ActionScript verziókban. Például ha egy osztály zárt, akkor egy ilyen osztály példányának nem kell hashtábla, hogy számontartsuk a dinamikus attribútumok hozzáadása szempontjából, és mégis egy kicsivel többet tárol el a jelleg objektum, mint egy mutató. Vagyis hogy a számok nyelvén kifejezzük a dolgot: egy olyan objektum, aminek a helyfoglalása ActionScript2.0-ban 100 bájt volt az ActionScript 3.0-ban olyan 20 bájt memóriát foglal el.

A prototípus objektum

ActionScript 1.0
ActionScript 1.0-et úgy azonosítják, mint az a nyelv, amit a Flash Player 6 vagy korábbi változatai használnak. A fejlesztés e korai szakaszában, az ActionScript objektum modellje azon az elgondoláson alapult, hogy az objektum nem más, mint egy alapvető adattípus. Egy ActionScript objektum nem más, mint egy adattípus csokorba kötve attribútumok egy csoportjával. Amikor az objektum modellt tervezték abban állapodtak meg, hogy mindent attribútumnak fognak hívni, amit egy objektumhoz hozzá lehet adni, mint például változók, függvények, és metódusok. Habár ez az első generáció nem támogatta az osztályok definiálását a class kulcsszó segítségével, mégis lehetett osztályt létrehozni egy speciális objektumfajta felhasználásával. Ezt nevezték prototípus objektumnak. A prototípus-alapú nyelvek, mint az ActionScript 1.0 egy már létező objektumot használnak modellként (vagy prototípusként) hogy más objektumokat létre tudjanak hozni. Amíg az osztály alapú nyelveknél az objektumok az osztályra mutatnak, és az osztály szolgál az objektum sablonjaként, addig a prototípus alapú nyelvek esetén az objektum egy másik objektumra mutat, ami a prototípus, és a prototípus szolgál az objektum sablonjaként. Ahhoz hogy létrehozz egy osztályt ActionScript 1.0-ben, definiálnod kell az osztály konstruktor függvényét. ActionScript-ben a függvények tényleges objektumok és nem csak absztrakt definíciók. Az általad létrehozott konstruktorfüggvény szolgál prototípusként az osztály többi példánya számára. A következő kód létrehoz egy Shape-nek elnevezett osztályt, és hozzáad egy visible nevű attribútumot, aminek alapértelmezett értéke true:
// base class 
function Shape() {} 
// Create a property named visible. 
Shape.prototype.visible = true; 
Ez a konstruktor definíció definiálta a Shape osztályt, amit a következő operátorral példányosíthatsz:
myShape = new Shape(); 
Egy olyan osztály létrehozása, amely egy másik osztályból származik már egy kétlépéses folyamat. Az első lépésként létrehozzuk azt az osztályt a konstruktorával, amit származtatni akarunk, a következő módon:
// child class 
function Circle(id, radius) 
{ 
	this.id = id; 
	this.radius = radius; 
}
Második lépésként a new operátor használatával adjuk meg azt, hogy a Shape osztály a prototípusa a Circle osztálynak. Alapértelmezésként minden olyan osztály, amit a felhasználó létrehoz az Object osztály prototípusából származik. Ahhoz hogy a Circle.prototype értékét megváltozasuk a következő kódot kell használni:
// Make Circle a subclass of Shape.
 Circle.prototype = new Shape();
Most már a Shape és Circle osztályok egymással öröklődési viszonyban vannak, ami azt jelenti, hogy egy prototípusláncot alkotnak. A diagram illusztrálja ez számunkra:
A öröklődés prototípus lánca
Az összes prototípus lánc legfelső szintjén mindig az Object osztály áll. Az Object osztály tartalmazza azt a statikus attribútumot, amit úgy nevezünk, hogy Object.prototype és ez mutat az alap prototípus objektumra, amivel az összes objektumot létre tudjuk hozni ActionScript 1.0-ben. A következő objektum ebben a példa prototípus láncba a Shape prototípus objektum. A Shape.prototype az Object.prototype-ra mutat leszármazottja az Object osztálynak. A lánc utolsó „szeme” a Circle osztály előzőekhez hasonlóan, vagyis a Circle osztály a Shape leszármazottja ezért a Shape.prototype-ra mutat a láncban. Ha a Circle osztálynak egy példányát létrehozzuk, mint ahogy azt a következő példában is látjuk akkor a példány a prototípuslánc Circle osztály egy leszármazottja lesz:
// Create an instance of the Circle class. 
myCircle = new Circle(); 
Emlékszünk még arra, hogy a Shape osztálynak van egy visible névre hallgató adattagja. A példában ez az adattag nem érhető el, mint myCircle objektum egy része, csak úgy, ha a Shape objektum egy adattagja, mégis a következő kódsor hatására true lesz a kimenet:
trace(myCircle.visible); // true 
Flash Player visszafele lépkedve a prototípus láncon képes megállapítani azt, hogy a myCircle objektum örökölte a visible attribútumot. Amikor futtatjuk ezt a kódot akkor a Flash Player először végignézi a myCircle objektum attribútumait, hogy van-e benne visible névre hallgató, de azt látja, hogy nincs ezért tovább megy. Flash Player azt látja, hogy a következő a Circle.prototype objektum, de még ennek sem talál olyan attribútumát, amit visible-nek neveznének. A keresést addig folytatja felfele a prototípusláncon, míg végül megtalálja a definiálásának helyén jelen esetben a Shape.prototype objektumban és kiírja az adattag értékét.
ActionScript 2.0
ActionScript 2.0 bevezetett új kulcsszavakat, olyanokat, mint class, extends, public, és private, amik lehetővé teszik számodra, hogy osztályokat hozz létre olyan módon, mint az már ismert osztály alapú nyelvek esetében, olyanokban, mint Java vagy C++. Ez fontos ahhoz, hogy megértsd azt, hogy nincs alapvető változás az öröklődési mechanizmusban ActionScript 2.0-ben ActionScript 1.0-hez képest. ActionScript 2.0 csupán új szintaxist adott arra, hogy osztályokat tudj definiálni. A prototípusláncok ugyanazon a módon működnek, mint eddig. Megjegyzem, hogy az ActionScript 2.0 bevezette a típus kiírást, ami a fordítási idejű típusellenőrzést segíti. Az extends kulcsszó egyszerűsítette az alosztályok készítésének folyamatát. A következő példában az ActionScript 1.0-ben kétlépéses folyamat leegyszerűsödését mutatjuk meg:
// child class 
class Circle extends Shape 
{
	var id:Number; 
	var radius:Number; 
	function Circle(id, radius) 
	{
		this.id = id; 
		this.radius = radius; 
	}
}
A konstruktor most már az osztálydefiníció részeként tekinthető, és az id és radius adattagok is explicit módon deklarálhatók. ActionScript 2.0 továbbá támogatást adott az interfészek létrehozásához.
ActionScript 3.0
Minden ActionScript osztály objektumnak van egy attribútuma, amit prototípusnak nevezünk, és az osztályok prototípus objektumára mutat. A prototípus objektum az ActionScript prototípus alapú nyelv gyökereiből származik. A prototípus attribútum csak olvasható, ami azt jelenti, hogy nem módosítható az, hogy melyik objektumra mutat. Az előző verziókhoz képest ez eltérés az osztály prototípus objektumoknál, mert ott újra ki lehet jelölni, vagyis meg lehet mondani, hogy melyik osztályra, mutasson. Habár a prototípus attribútumok csak olvashatók, a prototípus objektum, ami egy referencia nem csak olvasható. Más szóval új attribútumokat is definiálhatunk a prototípus objektumba. A prototípus objektumhoz hozzáadott attribútumokat az adott osztály összes példánya használhatja. A prototípus lánc, ami az egyedüli öröklődési mechanizmus volt az előző ActionScript verziókban, csak másodlagos szerepkörrel rendelkezik ActionScript3.0-ban. Az elsődleges öröklődési mechanizmust a kötött attribútumok öröklése jelenti, amit belül kezelnek le a jelleg objektumok. A kötött attribútum lehet változó, vagy metódus, ami az osztály részeként van definiálva. A kötött attribútum öröklődés nevezhető osztályok öröklődésének is, mert ez egy öröklődési mechanizmus, ami kapcsolatban van olyan kulcsszavakkal, mint a class, extends vagy override. A prototípuslánc egy olyan alternatív öröklődési mechanizmust nyújt, ami sokkal dinamikusabb, mint a kötött attribútumos öröklődés. Hozzáadhatsz olyan attribútumokat az osztály prototípus objektumához, ami nem része az osztály definíciójának, de futási időben az osztály objektum prototípusának attribútuma. Megjegyezem azonban, hogy ha a fordítást strict módban végzed, nem tudsz a prototípus objektumhoz attribútumokat hozzáadni, hacsak az osztályt nem dinamikusan deklaráltad. Egy jó példa az osztályok közül az Object osztály, amelynek számos prototípushoz csatolt attribútuma van. Az Object osztály toString() és valueOf() metódusai valójában az Object osztály prototípusához hozzácsatolt függvények. A következő példában meglátjuk, hogyan lehet egy ilyen függvényt definiálni:
public dynamic class Object 
{ 
	prototype.toString = function() 
	{
		// utasítások 
	};
	prototype.valueOf = function() 
	{
		// utasítások 
	}; 
}
Ahogy az előbb említettük, hozzácsatolhatunk egy attribútumot az osztály prototípus objektumához az osztálydefiníción kívülről is. Például a toString() metódust definiálhatod az osztálydefiníción kívülről is. Ezt mutatja a következő példa is:
Object.prototype.toString = function() 
{ 
	// uatsítások
};
Eltérően a kötött attribútum öröklődéstől a prototípus alapú öröklődés nem várja el az override kulcsszót, ha újra akarjuk definiálni egy metódust a leszármazott osztályban. Például ha a valueOf() metódust akarod újradefiniálni az Object osztály egy leszármazott osztályban, akkor három választásod van. Az első hogy definiálsz egy valueOf() metódust az alosztály prototípus objektumában az osztálydefiníción belül. A következő kód az Object osztály egy alosztályát definiál, amit Foo-nak nevezünk el, és újradefiniáljuk a valueOf() metódust az osztály prototípus objektumában az osztálydefiníción részeként. Ezt azért tehetem meg, mert minden osztály az Object osztályból származik anélkül, hogy használnánk az extends kulcsszót.
dynamic class Foo 
{ 
	prototype.valueOf = function() 
	{
		return "A Foo egy példánya"; 
	}; 
}
Második lehetőség hogy a valueOf() metódust a Foo prototípus objektumához hozzáadom az osztálydefiníción kívülről. Ezt mutatja a következő kód:
Foo.prototype.valueOf = function() 
{
	return "A Foo egy példánya"; 
};
A harmadik lehetőség hogy definiálsz egy kötött attribútumot az osztályon belül és azt nevezed el valueOf()-nak. Ez a lehetőség különbözik a többitől abban, hogy keveri a kötött attribútumos és a prototípus alapú öröklődést. Minden olyan osztály, ami a Foo osztályból származik, és újra akarja definiálni a valueOf() metódust annak használni kell az override kulcsszót. A következő kód azt mutatja, amikor a valueOf() metódus a Foo osztály kötött attribútumaként van definiálva:
class Foo 
{ 
	function valueOf() 
	{
		return "A Foo egy példánya"; 
	}
}

2. Öröklődés

1. Öröklődés szimulálása (dinamikus szemlélet)

Az öröklődés modellezése kicsit bonyolultabb, de elérhető a dinamikus kötés megvalósítása annak függvényében, hogy milyen konstruktor hozta létre az objektumot.

Példa öröklődés szimulálására

	function Téglalap(magasság, szélesség)
	{
			this.magasság = magasság;
			this.szélesség = szélesség;
	}
	  
	Téglalap.prototype.getTerület = function()
	{
			return (this.magasság * this.szélesség);
	}
	  
	Téglalap.prototype.toString = function()
	{
			return ("a="+this.magasság+", b=" + this.szélesség + " -> T="+this.getTerület());
	}
	  
	function Négyzet(oldalszélesség)
	{
			Téglalap.call(this, oldalszélesség, oldalszélesség);
	}
	  
	Négyzet.prototype = new Téglalap;
	t1 = new Téglalap(10, 20);
	n1 = new Négyzet(15);
	n2 = new Négyzet(Infinity);
	trace(t1); // a=10, b=20 -> T=200
	trace(n1); // a=15, b=15 -> T=225
	trace(n2); // a=Infinity, b=Infinity -> T=Infinity
	
Érezhető, hogy az objektum alapú szemlélet képes leírni szinte mindent, amit egy hagyományos osztály alapú szemléletben meg tudunk tenni, de van egy hatalmas problémája, ami miatt ki akarták terjeszteni ezt a rendszert. Mivel nincsenek benne típusellenőrzések, így szinte lehetetlen „fordítási” idejű hibaüzeneteket adni, és ez jelentősen csökkenti a program megbízhatóságát.

2. Öröklődés (osztály alapú szemlélet)

Az AS-ben lehetőség van egy tetszőleges hosszú öröklődési lánc kialakítására. Öröklődéskor az új, úgynevezett alosztály (SubClass) örökli a már meglévő osztály (SuperClass) tulajdonságait, illetve függvényeit, mindazonáltal további metódusokat és adattagokat definiálhatunk az alosztályban, ezért is nevezik az eljárást kiterjesztésnek (extends).

Öröklődésre az extends kulcsszó használható:

	class SubClass extends SuperClass {}
	

Sok beépített osztályból is lehet származtatni, de például nem származtathatunk a TextField osztályból, és a statikus osztályokból sem, mint: Math, Key és Mouse osztály. Ha nem hívjuk meg a super() metódussal a szülő osztály konstruktorát a leszármazott konstruktorából, akkor a fordító automatikusan generál egy hívást a közvetlen szülőjének konstruktorára paraméterek nélkül, és ez lesz a metódus első utasítása. Ha a szülőben nincs konstruktor, akkor a fordító készít egy üreset, és meghívja ezt a leszármazottból. Azonban ha a szülőben paraméterek is vannak a konstruktorban, akkor a leszármazottban kell írni konstruktort, ami meghívja a szülő konstruktorát a megfelelő paraméterekkel. Felmerülhet annak az igénye, hogy a kiterjesztett osztályban egy olyan metódust akarunk írni, amely nevében megegyezik a szülő osztályban szereplő metódussal.(Pl. Egy toString() művelet másfajta implementációjára lehet gondolni.) Ez egyszerűen megtehető, mivel ekkor a származtatott osztály metódusa fog lefutni a metódus hívásakor (vagyis overrideoltuk a metódust).

A változók és konstansok öröklődnek, de nem definiálhatóak felül, a statikus adattagok (tehát az osztályváltozók) pedig nem öröklődnek, de elérhetőek, viszont azonos nevű változót létrehozva az elfedi az osztályváltozót.

3. Package-ek

Ha több összefüggő osztályunk is van, például:

	// In Square.as:
	class Square {}
	// In Circle.as:
	class Circle {}
	// In Triangle.as:
	class Triangle {}
Akkor érdemes őket összefogni egy Shape package-be. Tehát a package, arra használható, hogy az azonos funkciójú osztályokat egy egységbe foglalja. Egy package tartalmazhat más package-eket is. Egy package-nek azonosítónak kell lenni, tehát meg kell, hogy feleljen az azonosító formájára vonatkozó előírásoknak. Ha egy osztályra szeretnénk hivatkozni, akkor ezt megtehetjük úgy, hogy megadjuk az elérési útját, vagy importáljuk azt a csomagot, ami őt tartalmazza. Tegyük fel, hogy van például egy Data osztályunk a com/xyzzycorporation/ package-ben. Ha ebből az osztályból szeretnénk példányosítani, akkor azt megtehetjük a következőképpen:
	var dataInstance = new com.xyzzycorporation.Data(); 
	
Vagy így:
var dataInstance:com.xyzzycorporation.Data = new Data(); 
	
De akár importálhatunk is, ha mondjuk létrehozunk egy UserClass osztályt a com/xyzzycorporation/util/users könyvtárban:
	// In the file com/xyzzycorporation/util/users/UserClass.as
	class com.xyzzycorporation.util.users.UserClass { ... } 
	
Akkor az importálás egy scriptből:
	import com.xyzzycorporation.util.users.UserClass; 
	
Így később ugyan abban a scriptben, már hivatkozhatunk erre az osztályra rövidebben is:
	var myUser:UserClass = new UserClass(); 
	
Ha egy adott package-ből az összes osztályt be szeretnénk importálni, akkor használhatunk * - ot:
import com.xyzzycorporation.util.*; 
	

4. Interfészek

Az öröklődés használatával tehát lehetőség nyílik osztályok tulajdonságainak, és metódusainak „átvételére”. Viszont mi van akkor, ha egy olyan osztályt szeretnénk, amely egy időben több másik osztállyal áll SubClass-SuperClass viszonyban? Ez az elgondolás a polimorfizmus. Több magas szintű programozási nyelv megengedi a több osztályból való származtatást, pl. a C++ is, de az ActionScript nem tartozik ezek közé. Viszont ennek orvoslására találták ki az interface-eket.

Interfészeket az interface kulcsszó segítségével hozhatunk létre:

	public interface interfaceName { az interface metódusainak deklarációi }
	public interface interface2Name { az interface metódusainak deklarációi }
	
Majd ezt az implement kulcsszóval implementálhatjuk:
	class className implements interfaceName, interface2Name {az interface metódusainak megvalósítása}
Egy interfészben csak metódusok/függvények deklarációja szerepelhet paraméterekkel, paramétertípusokkal és a visszatérési érték típusával. Változó, vagy értékadás nem szerepelhet interfészben.