Ultrashock Tutorials > Flash MX 2004 > ActionScript 2.0  
 
by Dave Yang, quantumwave.com - swfoo.com
Download Source Files 
 
ActionScript 2.0
 

01. Introduction
02. A little bit of OOP in ActionScript 1.0 
03. What's new in ActionScript 2.0?

04. New keywords and features for OOP
05. Scope and "this"
06. Private or protected?
07. Dynamic vs Static classes

08 Inheritance.
09. Overriding, Overwriting or Overloading?

10. Importing external class files
11. Interface
12. What is missing in ActionScript 2.0?
13. Conclusion

- discuss this tutorial -

04. New keywords and features for OOP

It's time to get into the actual language features of ActionScript 2.0. As discussed earlier, object-oriented programming in ActionScript 1.0 involved more work than necessary. As you will soon see, with ActionScript 2.0, you don't have to spend time debating how best to do inheritance, where to place code and how to organize code libraries.

Let's review the basics of OOP. The fundamental unit of OOP is an object, which contains two things: code and data. Because objects are supposed to be self-contained, this data and code (methods) are not necessarily for public consumption. As blackboxes, objects are responsible for managing their own data with their own methods. Objects communicate with other objects by sending messages; these messages are sent and received using public methods (also known as an API or Application Programming Interface) so that internal data is not manipulated directly. This is the basic idea of OOP.

In object-oriented design, consider the big picture, think of the leading items and objects, and determine how these objects talk to each other. By breaking up the big picture into smaller units, and making each unit self-contained and self-responsible, an application can be built with managed ease. This idea of a unit is called a class in OOP, which ActionScript 2.0 officially supports.

Here is the list of new keywords related to OOP:

class interface extends implements
public private static dynamic
import get set intrinsic

We'll not duplicate Macromedia documentation and describe each of these keywords; instead, working examples will demonstrate what they do. Note: The keyword intrinsic is intended for Macromedia internal use only. There is no 'package' keyword, but the way import works with class paths is almost the same as packages in other languages, such as Java.

Let's take a look at a simple example of setting up a class in ActionScript 1.0 (see Parent_AS1.fla), and its translation to ActionScript 2.0:

// constructor
_global.Parent = function(name) {
   this.init.apply(this, arguments);
};
// a class (static) property
Parent.lastNames = new Array();
Parent.prototype.init = function(name) {
   this.lName = name;
   Parent.lastNames.push(name);
   this.id = Parent.lastNames.length-1;
   trace("Added '"+ Parent.lastNames[this.id] +"' at: "+ this.id);
};
Parent.prototype.getLastName = function() {
   return (this.lName);
};
Parent.prototype.setLastName = function(s) {
   this.lName = s;
   Parent.lastNames[this.id] = s;
};
Parent.prototype.getNames = function() {
   return (Parent.lastNames);
};
Parent.prototype.addProperty("lastName", Parent.prototype.getLastName, 
Parent.prototype.setLastName); Parent.prototype.addProperty("names", Parent.prototype.getNames, null);

The code above translated to ActionScript 2.0 would look something like this (refer to Parent.as):

New keywords used in this example: class, private, public, static, get, set

class Parent {
   private var lName:String = "";
   private var id:Number;
   private static var lastNames:Array = new Array();
   // constructor
   public function Parent(name:String) {
      init.apply(this, arguments);
   }
   private function init(name:String):Void {
      lName = name;
      lastNames.push(name);
      id = lastNames.length-1;
      trace("Added '"+ lastNames[id] +"' at: " + id);
   }
   public function get lastName():String {
      return lName;
   }
   public function set lastName(s:String):Void {
      lName = s;
      lastNames[id] = s;
   }
   public function get names():Array {
      return lastNames;
   }
}

Notes for advanced programmers

Flash compiles all non-static properties (e.g., lName and id) outside of the constructor and attaches them to the prototype object of the class; unlike the AS1 version we coded by hand, where these properties were in each instance. In fact, in the init() method where the statement lName = name goes, a new property with the same name (lName) is created that overrides the one in the prototype object. To verify this, you can try to delete instance.lName and then do a trace(instance.IName). If the lName property in the prototype object has a different value than the instance property lName, you will see the difference. Non-primitive objects (such as Array and Object), when placed in the prototype, are shared among all instances, making them act like static properties (i.e. changing one affects all instances). If you need to have non-primitive instance properties, they must be initialized in the constructor or inside a method (thereby creating a new property of the same name in the instance that overrides the default).

The following code demonstrates this issue:

// NonStaticNonPrimitivePropertyTest.as
class NonStaticNonPrimitivePropertyTest { private var myArr:Array = new Array();
public function addToMyArr ( someThing:Object ) : Void { myArr.push ( someThing ); } public function displayMyArr ( Void ) : Void { var l:Number = myArr.length; for ( var i=0; i < l; i++ ) { trace (" myArr["+ i +"] = " + myArr[i]); } } }
// nonStaticNonPrimitivePropertyTest.fla
var myFirstTestInstance:NonStaticNonPrimitivePropertyTest =
new NonStaticNonPrimitivePropertyTest();
var mySecondTestInstance:NonStaticNonPrimitivePropertyTest = 
new NonStaticNonPrimitivePropertyTest();
myFirstTestInstance.addToMyArr("This should only 
appear in first instance");
trace("1. myArr in myFirstTestIntance:");
myFirstTestInstance.displayMyArr();
trace("\n"); // empty line
mySecondTestInstance.addToMyArr("This should 
only appear in second instance");
trace("2. myArr in mySecondTestInstance:");
mySecondTestInstance.displayMyArr();
trace("\n"); // empty line
trace("3. myArr in myFirstTestIntance:");
myFirstTestInstance.displayMyArr();
The output from this, as mentioned above, is not as expected:

 


You may not be familiar with apply(), the method I've used in the Parent class' constructor. There are three ways to invoke functions in ActionScript: The first (and simplest) way is to simply state the name of the function along with paranthesis and include any arguments you are passing to the function within the paranthesises, as shown below:

myFunction(myFirstArgument, mySecondArgument);

The second way is to dynamically form the function reference using an object reference and funtion name string, as shown below:

var myObjectReference = _root;
var myFunctionName = "myFunction";
myObjectReference[myFunctionName] (myFirstArgument, mySecondArgument);
The final method, and the one I've used above, is to use the apply() method of a function. When calling a function via apply(), you can define the object that the function is applied to (as the first argument) and pass in an array of arguments for the function (as the second argument). The first argument determines the scope of the function and the value that this will have for the function. The arguments passed to a function are available to the function in an array called arguments.
var myObjectReference = _root;
myArguments = [ myFirstArgument, mySecondArgument ];
myFunction.apply ( myObjectReference, myArguments );

Looking through the AS1.0 and AS2.0 implementation of the same class, you can see that they are quite similar.
The main differences in ActionScript 2.0 are:

  • A class is defined in an external .as file, with each class in its own file with the filename matching the class name
  • ActionScript 2.0 is case-sensitive, meaning that the words 'object' and 'Object' are different
  • Class methods are defined inside the class
  • No inner class is allowed (internal functions are allowed as expected)
  • Keywords and modifiers such as private, public, static are used in front of method and property names.
    If both public and private are left out, the method or property is public by default
  • Data types are placed after method and property names, in the following format: name:type
  • Creating getter and setter methods is now easier with the following syntax: [modifier] function get|set functionName(argument[:type,...])[:type] {}


- discuss this tutorial -
 
©2003 Ultrashock.com - All rights reserved