More classes
Private Constructor and class extensionWhen you create a class, which extends another class, the word this is used. However, there are a several problems associated. Referring to this within an object method will not refer to the superclass but to the object itself. Using this._parent does not solve the problem. Therefore, we have to create a var holding this as a value. Depending on the superclass this var will have different datatype such as MovieClip or others. Then within the object method we use this var. We fill the var within the constructor as shown below. This saves us some typing. At the same time we declare the constructor as private so it cannot be accessed from outside because it is private. For this tutorial create a movieclip, name it square for example and put this line in the AS2 class line: as_scripts.Constructor1. Then in the fla file add this line: _root.square.showVar(); and test the movie.
class as_scripts.Constructor1 extends MovieClip {
private var m_mc:MovieClip;
private var n_timer:Number;
private var f_function:Function;
private function Constructor1 () {//constructor cannot be accessed
m_mc = this;
}
public function showVar () {
var mo_mc:MovieClip = m_mc;
n_timer = setInterval (f_function, 500);
function f_function () {
trace(mo_mc);//refers to the superclass
}
}
}
| Top |
Using the Delegate class for referencing within a functionThere is another way to write the above class script with the same result using the Delegate class. By calling this class objects within object methods like interval will stay objects of the class. We first import the Delegate class and then we refer to it when we create the interval function by writing Delegate.create(this, f_function), which refers to the class and the function we create. The result will be the same.
import mx.utils.Delegate;
class as_scripts.Constructor2 extends MovieClip {
private var n_timer:Number;
private var f_function:Function;
public function Constructor2 () {
}
public function showVar () {
//will keep the reference to the superclass
n_timer = setInterval (Delegate.create(this, f_function), 500);
function f_function () {
trace(this);//refers to the superclass
}
}
}
Fla file:
_root.square.showVar();
We can also pass function parameters as shown in the next example. Place the parameters after the interval time. However, the function parameters are not passed on by the Delegate class but by the interval function.
import mx.utils.Delegate;
class as_scripts.Constructor2 extends MovieClip {
private var n_timer:Number;
private var f_function:Function;
public function Constructor2 () {
}
public function showVar () {
var test1:Number = 10;
var test2:Number = 5000;
n_timer = setInterval (Delegate.create(this, f_function), 2000, test1, test2);
function f_function (test1:Number,test2:Number) {
trace("test1: "+test1);//trace is 10
trace("test2: "+test2);//trace is 5000
trace(this);
}
}
}
Fla file:
_root.square.showVar();
Delegate can be used for extending the scope of a number of other function such as listeners and xml parsing. | Top |
Functions with parametersAlthough this is ok for interval and probably some other object functions, there will be problems passing variables with functions like event handlers. This has been solved by the Proxy class, which you can download at this site. Unlike the Delegate class the Proxy class allows the passing of function parameters without redefining. The following script is an example.
import mx.utils.Proxy;
class as_scripts.Constructor4 extends MovieClip {
private var f_function:Function;
public function Constructor4 () {
}
public function showVar () {
var test1:Number = 10;
var test2:Number = 5000;
//var a:Proxy = new Proxy();
this.onEnterFrame = Proxy.create(this,f_function,test1, test2);
function f_function (test1:Number,test2:Number) {
trace("test1: "+test1);
trace("test2: "+test2);
trace(this);
}
}
}
Fla file:
_root.square.showVar();
For convenience put the .as file in the mx.utils folder, where the Delegate class is stored. | Top |Problems with getterAlthough this may not occur to you but there can be a problem that a getter method will give undefined for a var even the var is called in a function. Let's look at the class script first. The script is a regular script with a public var of datatype String.
CLASS script:
class as_scripts.Gettera {
public var myVar:String;
public function Gettera () {
}
public function newClass ():Void {
myVar = "Hello";
trace("newClass: "+myVar);
}
public function get newVar ():String {
return myVar;
}
}
FLA file script:
import as_scripts.*;
var a:Gettera = new Gettera();
trace("getter: "+a.newVar);//will give undefined
a.newClass();
If we call the getter first we will have undefined for the trace action and Hello for the function call. Now let's change the order of the calls as shown below using the same class script:
FLA file script:
import as_scripts.*;
var a:Gettera = new Gettera();
a.newClass();
trace("getter: "+a.newVar);//will give "Hello"
This means that a getter method will only give a value if the a function is executed, where the var to be called has been defined. | Top |Accessing a variable from the classLet's say you have a variable myVar, which occurs in the movie somewhere and you need to access this variable in a class script. Then you can do that in the following way in exactly this order.
FLA file script:
var myVar:Number = 3;
var a:Access = new Access();
trace(a.getNumber);//gives 3
CLASS script:
class Access {
var myVar:Number;
public function Access(){
}
public function get getNumber():Number{
return _root.myVar;
}
}
| Top |
Bad coding: Accessing a private varWell, so far you learnt that it is not possible to access a private variable from the movie. Actually it is possible but of course not recommended. Depending on how you call the class private vars can be accessed. The normal case to call a class would be as shown in the example below:
FLA file script:
import as_scripts.*;
var a:PrivVar = new PrivVar ();//correct usage
trace(a.myVar);
CLASS script:
class as_scripts.PrivVar {
private var myVar:String;
function PrivVar () {
myVar = "Hello";
}
}
This, however, would give an error message because you tried to access a private member of a class. The following script in your fla file would not:
FLA file script:
import as_scripts.*;
var a = new PrivVar();//WRONG usage
trace(a.myVar);
We are omitting the datatyping of the var a and that allows the access of a private member. So rule No 1 in actionscript is the DATATYPING of all var in the fla file as well as in the class file. The problem here is that if we ommit datatyping in the fla file there is no error message. Remember that in Flash MX2004 AS1 as well as AS2 is possible and can be mixed. Strictly spoken AS2 scripts should all contain var with datatyping. May be the next generation of Flash editions will have that. In the next lesson we discuss a special type of datatyping called casting. |