OOP - POO / AS1 - AS3

Professeur Pirson Nicolas Pirson :
Go to my website : tatactic.be [FR] (Website about hepatitis)
nicolas.pirson.me [FR - EN] (current website)
business card - blog [FR - EN] (just for fun)
Nicolas Pirson CV page [FR] on tatactic.be
Back to AS3 - FLASH index ... [EN]

Last modified : 2010-09-21

Basics : AS1 , javascript : prototype , constructor,
__proto__ , __constructor__


ActionScript 1 and prototyping...
Or using a function as an Object or a dynamic class (AS3) in AS1.

Level : beginners **

In AS1 the use of prototype was more or less equivalent to create a dynamic class in AS3
The use of ASSetPropFlags (undocumented for a while then deprecated, was a way to protect variables or methods against override)... example of use : ASSetPropFlags(obj,props,n,allowFalse).
Because all prototypes were implicitly dynamic, you can figure you out the importance to protect a little bit your Objects or variables...
But let's forget this for now...

All Objects are Objects (MovieClip, String, Array ...)

So in Actionscript 1 , an Object is a dynamic class, and therefore all Objects who inherits of the Object object are dynamic. You can then add methods or change methods and properties at runtime...
Be careful !
This looks easy, but everybody can overwrite your own methods even if they shouuld not be overrided.
IT WILL NOT THROW ANY ERROR!

In AS1 :

MovieClip instanceof Object => true
String instanceof Object => true
Array instanceof Object => true



obj = new Object();

// obj.__constructor__.prototype.someValue = "Some value";
// Comment because this will only work since player 6!


obj.constructor.prototype.someValue = "Some value";

/*
This will work when exporting for flash player 5 and above too...
The scope and use of __constructor__ or constructor can be different,
So TEST, TEST, TEST...
Copy paste is easy, but if you really want to understand, try to publish in different versions.
Your skills an comprehension of the scope in flash will be improved!
*/

trace (obj.someValue);
//Output : Some value

var object2 = new Object();
trace (object2.someValue);
//Output : Some value

This is the equivalent to :

Object.prototype.someValue = "Some value";
var obj = new Object();
trace(obj.someValue);


OR :

Object.prototype.someValue1 = "Some value1";
Object.prototype.someValue2 = "Some value2";
Object.prototype.someValue3 = "Some value3";
Object.prototype.getSomeValue = function(val){
return (this[val]); }

var obj = new Object();
trace(obj.getSomeValue("someValue2"));
//Output : Some value2

If you want to add functions directly to the MovieClip prototype :
You can do it like this in AS1...


Extend MovieClip Object prototype in AS1 :

MovieClip.prototype.place = function(px,py){
this._x = px;
this._y = py;
}
mc_1.place(200,300) ;

you just need to have an instance of MovieClip on the TimeLine named "mc_1"
And so on for each Object...

Math Object in AS1 ... :

For static methods like Math methods that you can add your methods like this :

Math.fractal = function(nb){
if((Math.round(nb) % nb) != 0){
trace("this is not an uint variable!!!");
trace("ERROR FUNCTION WILL EXIT!!!");
return 1;
}
if(nb<=1){
return1
}
if(arguments.caller == nul){
init = nb;
}
if((nb>=2)){
init = init * (nb-1); this(arguments.callee(nb-1));
}
return init;
}

var b = 5;
var c = Math.fractal(b);
trace("fractal result = " + c)
// return 5 * 4 * 3 * 2 * 1 = 120
// output : fractal result = 120

same fractal function in AS3 ... :

For static methods like Math methods that you can add your methods like this :

var init:uint;
function fractal (nb:uint,ini:uint=1){
if(ini <= 1){
init = nb;
}
if((Math.round(nb) % nb) != 0){
trace("this is not an uint variable!!!");
trace("ERROR FUNCTION WILL EXIT!!!");
return 1;
}
if((nb>=2)){
trace("init = " + init)
init = init * (nb-1);
fractal((nb-1),init);
}
if(nb<=1){
return 1
}
return init;
}

var b = 5;
var c = fractal(b);
trace("fractal result = " + c)
// return 5 * 4 * 3 * 2 * 1 = 120
// output : fractal result = 120

finally AS3 to AS1 Compatible,
just change the declarations like this :
function fractal for AS1

var init;
function fractal (nb,ini){
if(ini <= 1){
init = nb;
}
if((Math.round(nb) % nb) != 0){
trace("this is not an uint variable!!!");
trace("ERROR FUNCTION WILL EXIT!!!");
return 1;
}if((nb>=2)){
trace("init = " + init)
init = init * (nb-1);
fractal((nb-1),init);
} if(arguments.caller == nul){
init = nb;
} if(nb<=1){
return 1
}
return init;
}

In Javascript now :

javascript code : JS Math fractal . js
The file :

// JavaScript Document
Math.fractal = function(nb,ini){
if(isNaN(ini)){
init = nb;
alert ("called init");
}
if((Math.round(nb) % nb) != 0){
//trace("this is not an uint variable!!!");
//trace("ERROR FUNCTION WILL EXIT!!!");
return 1;
}
if((nb>=2)){
alert("init = " + init)
init = init * (nb-1);
Math.fractal((nb-1),init);
}
if(nb<=1){
return 1
}
return init;
}

So when calling the fractal() function you get this :

On this page :
<script type="text/javascript">
//<![CDATA[
var b = 5;
var c = Math.fractal(b);
document.write("fractal result = " + c);
//]]>
</script>
<noscript>
<div>
javascript is disabled!
</div>
</noscript>

Javascript output and test of the function :


The Constructor function

function PersoObject(instName){
this.__proto__.name = instName;
// If you code also in PHP, you will never forget to place a semicolon at the end of each line of code :)
//__proto__ is used inside the methods to refer to the prototype
//prototype is used at runtime when accessing variables or methods

}
PersoObject.prototype.showInstance = function(){
return this.__proto__.toString(); }
PersoObject.prototype.showConstructor = function(){
return this.__constructor__.toString(); }

var myInstance = new PersoObject("name for this instance");
// Use a function as constructor
trace(myInstance.showInstance());
trace(myInstance.showConstructor());
trace(myInstance.name);
trace(myInstance.someVariable) ;

//output undefined for : trace(myInstance.someVariable)


PersoObject.prototype.someVariable = new String("hello world!");

//someVariable is now defined! So...
trace(myInstance.someVariable);
//output "hello world!" (someVariable is now defined in the prototype of PersoObject)
//All instances of Perso Object have now a property called someVariable

//ex now some variable is defined for all instances:
var anotherInstanceOfPersoObject = new PersoObject("name for the second instance of PersoObject");
trace(anotherInstanceOfPersoObject.showInstance());
trace(anotherInstanceOfPersoObject.showConstructor());
trace(anotherInstanceOfPersoObject.name);
trace(anotherInstanceOfPersoObject.someVariable);

So Output results :
// for trace(anotherInstanceOfPersoObject.showInstance()) ;
[object Object]
// for trace(anotherInstanceOfPersoObject.showConstructor());
[type Function]
// for trace(anotherInstanceOfPersoObject.name);
name for the second instance of PersoObject
// for trace(anotherInstanceOfPersoObject.someVariable);
hello world!

trace(anotherInstanceOfPersoObject.constructor);
// CONSTRUCTOR NOT __CONSTRUCTOR__

Output :
[type Function]

Try to understand the difference between :

constructor and __constructor__ , prototype and __proto__ Test when you must call them : __ __ or not __ __ ? That's the scope for this part :)

Why are you boring me with this old AS1 ?
Huh??? Javascript is the same as actionscript 1. So...
Yepee you're, ready for HTML5 and javascript. :)

So, why are you talking about ActionScrip 1?
Just because in javascript, you work like in AS1!
here's a basic JS_Object ...
This is the code in javascript-prototype/JS_Object.js :

// JavaScript Document
function JS_Object(){
//Empty constructor }
JS_Object.prototype.alertBox = function(msg){
alert(msg); }

And on this page :

<script type="text/javascript">
//<![CDATA[
var myAlertBox = new JS_Object();
document.write("<a href=\"javascript:myAlertBox.alertBox('My message in the alert box');\">see the alert message</a>");
//]]>
</script>



<noscript>
Javascript is not enabled
If enabled it will call the script that you can open/save or read here.(click enabled to view source)
var myAlertBox = new JS_Object();
document.write("<a href=\"javascript:myAlertBox.alertBox('My message in the alert box');\">see the alert message</a>");
</noscript>

You see? This is exactly the same as in Actionscript 1 !!!

Inheritance in AS1


In AS1 if you need to extend an Object ex with the Array Class:

It's really a peace of cake :
- this is the way to do it in actionscript 1

One way is to add Methods to All the instances of the Array Object (or another Object).
That's easy but not always a good job to override the Array Object or Array.prototype directly.


Array.prototype.listAnArray = function(){
for (var n = 0; n < this.length; n++){
trace("this [" + n + "] = " + this[n]) ;
}
}

arrayInstance = new Array();

arrayInstance = ["test 1", "test 2", "test 3", "test 4"];
arrayInstance.listAnArray();


//But REMEMBER THAT ALL INSTANCES OF ARRAY WILL HAVE A NEW METHOD CALLED listAnArray

Another way to extends the Array Object is to create a PersoArray Object, then

PersoArray = function(){
//empty;
}

PersoArray.prototype = new Array();
// So now PersoArray instnces will inherits the methods of the Array Object.

PersoArray.prototype.populate = function(){
this.__proto__[0] = "Hello";
this.__proto__[1] = " ";
this.__proto__[2] = "World";
this.__proto__[3] = " ";
this.__proto__[4] = "!";
// you can also use the push method if you want...
// because PersoArray.prototype = new Array();
//ex add some random datas :
for (var m = 0 ; m <= 5 ; m ++){
this.__proto__.push("randomVal_" + Math.round(Math.random()*100))
}
}

// this method will populate a PersoArray instance if called

PersoArray.prototype.listTheArray = function(){
var outputString = "";
for (var i = 0 ; i< this.__proto__.length ; i++){
outputString += this.__proto__[i];
if(i < this.__proto__.length - 1){
outputString += ", ";
} else{
outputString += ".";
}
}
return outputString;
}

PersoArray.prototype.greetings = function(){
trace("I'm an instance of PersoArray and called by my constructor : " + this.__constructor__);
}


var myPersoArrayInstance = new PersoArray();
myPersoArrayInstance.greetings();

/*
output :
I'm an instance of PersoArray and called by my constructor : [type Function]
I'm an instance and my prototype is : instance of PersoArray

*/
myPersoArrayInstance.populate();
// just populate the instance as an Array via the prototype.populate method
PersoArray.prototype.push("just a test");

// PersoArray.prototype is an Array! You can call the method push!
// You want to test it?
// Try this :

trace("myPersoArrayInstance instanceof Array? -> " + (myPersoArrayInstance instanceof Array));
trace("myPersoArrayInstance instanceof PersoArray? -> " + (myPersoArrayInstance instanceof PersoArray));

/*
output :
myPersoArrayInstance instanceof Array? -> true
myPersoArrayInstance instanceof PersoArray? -> true
*/

trace(myPersoArrayInstance.listTheArray());
/*
output : Hello, , World, , !, randomVal_88, randomVal_42, randomVal_35, randomVal_93, randomVal_65, randomVal_35, just a test.
*/


for (var j = 0 ; j< myPersoArrayInstance.length ; j++){
trace("myPersoArrayInstance[" + j + "] = " + myPersoArrayInstance[j]);
}

/* output :
myPersoArrayInstance[0] = Hello
myPersoArrayInstance[1] =
myPersoArrayInstance[2] = World
myPersoArrayInstance[3] =
myPersoArrayInstance[4] = !
myPersoArrayInstance[5] = randomVal_88
myPersoArrayInstance[6] = randomVal_42
myPersoArrayInstance[7] = randomVal_35
myPersoArrayInstance[8] = randomVal_93
myPersoArrayInstance[9] = randomVal_65
myPersoArrayInstance[10] = randomVal_35
myPersoArrayInstance[11] = just a test

*/


XHTML 1.0 STRICT. Compatible W3C CSS 2.0  Compatible W3C