An ActionScript 2.0 Primer for ActionScript 1.0 Folk: Part Two - By JOEY LOTT
www.person13.com
As promised in Part One of this article, in this second part we'll examine
the new class syntax in ActionScript 2.0. Before we get started, if you have
questions regarding general object-oriented concepts, including classes, then
you may want to first check out these two articles:
http://www.oreillynet.com/pub/a/javascript/2003/08/12/actionscriptckbk.html
http://www.oreillynet.com/pub/a/javascript/2003/08/19/actionscriptckbk.html
The two articles discuss object-oriented concepts and creating classes in
ActionScript 1.0, so you don't necessarily need to memorize all the details
of the ActionScript 1.0 techniques. But the articles should give you a pretty
good introduction to what classes and objects are in a general sense. Once you
have that background this article will likely make more sense to you.
ActionScript 2.0 Class Structure
While I could attempt to draw comparisons between ActionScript 1.0 "class"
structure and ActionScript 2.0 class structure, it would likely be more confusing
that clarifying. The truth is that ActionScript 2.0 class structure is fundamentally
different than that of ActionScript 1.0. If you have any background in creating
classes in other languages such as Java or C#, or even VB or PHP, then you'll
likely shout a loud hoorah for the new formal class structure in ActionScript.
If you're only prior experience with creating classes was with ActionScript 1.0,
then don't fret too much. You're sure to find that although the syntax in ActionScript
2.0 is different, it is much more intuitive. After a week writing ActionScript
2.0 classes you'll wonder how you ever managed with ActionScript 1.0.
To begin with, I'll highlight a few of the key points of the new class structure
and syntax, then we'll look at some of them more closely.
* ActionScript 2.0 classes must be defined in .as files, and there can only
be one class per file.
* ActionScript 2.0 classes are declared using the new class keyword followed
by the name of the class and then the body of the class surrounded in curly
braces. For example:
class Car {
// Class definition…
}
* ActionScript 2.0 classes can be in packages. ActionScript 2.0 supports the
import keyword in order to import entire packages
or select classes within packages.
* ActionScript 2.0 class members can be declared as public, private, and static.
* ActionScript 2.0 classes can extend other classes using the extends
keyword in the class declaration.
* ActionScript 2.0 classes can implement interfaces.
Whew! If any of that sound scary or new to you, keep on reading. I'm going
to explain each of these parts in more detail and with examples you can try
on your own (assuming you have a copy of Flash MX 2004 or Flash MX Professional
2004.)
Defining ActionScript Class Files
If you're not familiar with other languages such as Java or C# then storing
classes in their own files may be a new concept. Particularly so if you've worked
with ActionScript 1.0 in which you could define multiple classes not only within
a single .as file, but even within an .fla file.
There are plenty of reasons why it's advantageous to store all your classes,
one per file, in external .as files. The core benefit is, of course, better
organization. It's just simply much easier to store, locate, maintain, and distribute
your classes when they're organized well. If you're defining classes in all
kinds of places, then it becomes a mess rather quickly. Of course, if you were
only working with two or three classes, this would not necessarily pose a big
problem. But ActionScript 2.0 ushers in a new paradigm for ActionScript. Developers
can create and share libraries of classes that provide pre-built functionality.
Rather than reinventing the wheel each time people can begin to build upon their
own previous work and the work that others have contributed. You can see how
Macromedia has already jumpstarted this with their set of standard classes that
you can find in the First Run/Classes directory (and subdirectories) of your
Flash MX 2004 installation.
So unlike ActionScript 1.0 classes, all ActionScript 2.0 classes absolutely
must be saved in external .as files. Further more, these files must be saved
such that the file name matches the name of the class. For example, if the class
is named Car,
then the file must be named Car.as.
Working with Packages
Class files may be stored in packages. If you're not familiar with packages
(also called namespaces in the .NET world) they are simply a way of organizing
your classes. There are two aspects to a package. First, the class definition
must specify the package in its declaration. We'll look more closely at that
part in the next section. Secondly, the .as file must be saved in a corresponding
directory or directories. For example, if the package for a class is com.person13
then the .as file for that class must be saved in a directory structure of com/person13.
There are two primary benefits to working with packages. The most obvious one
is that it provides you with a way to organize your class files so that you
can locate them quickly. For example, if you look in the set of classes that
ship with Flash MX 2004 (in the First Run/Classes directory) you'll see that
many of the classes for the UI components are organized within the mx.controls
package, and are therefore saved in the mx/controls directory. The second benefit
of packages is that it helps to avoid possible name conflicts. You cannot have
two classes with the same name in the same package for the obvious reason that
Flash wouldn't have a way of knowing which one you want to use. So if you didn't
use any packages and saved all your classes in the same directory you would
potentially run into this problem. Of course, if you are writing all the classes
then you have the ability to easily make sure you give each class a unique name.
But when you download and install others' classes, you don't have that same
control. So when classes are stored in packages it helps to make sure that these
types of naming issues don't occur. For example, the class Car
in the com.person13 package and the class Car
in the com.ejepo package don't create any naming conflicts with Flash.
Defining Your Classpath
By default Flash looks first to the First Run/Classes directory within your
Flash installation when trying to find class files. If it does not find a specified
class in that directory then it next looks to the same directory in which the
Flash or ActionScript document is saved.
The classpath is the list of directories to which Flash looks for class files.
You can also specify additional directories for the classpath. And, if you want,
you can change the order in which Flash looks to these directories. In order
to edit the classpath choose Edit>Preferences, and then select the ActionScript
tab. Click on the ActionScript 2.0 Settings to bring up the ActionScript Preferences
dialog box. Use the + button to add new directories, the - button to remove
directories, and the arrow buttons to reorder them.

Figure 1: defining the classpath
As you can see in Figure 1, I've added the directory D:\ActionScriptClasses
to my classpath. This means that the third place that Flash will look for class
files is now D:\ActionScriptClasses. (Incidentally, $(LocalData) resolves to
the First Run directory of your Flash installation.) Adding a custom directory
to the classpath can be a good idea for a few reasons:
* It can be easier to browse to a directory such as D:\ActionScriptClasses than
to the directory in which Flash stores all classes that ship with Flash.
* It is easier to manage your files if you save all your custom classes in a
directory other than the directory into which Flash stores classes that ship
with Flash.
Understanding Private and Public Members
A class is composed of members - properties and methods. Unless you used some
convoluted or undocumented features of ActionScript 1.0, all ActionScript 1.0
members were public. When we say that a member is public, it means that it can
be accessed from outside of the class definition. For example, if you create
a Car class with
a property named make, and that property can be accessed from an instance of
the Car class,
then the property is public. But there are plenty of times in which you don't
want the properties and methods of a class to be publicly accessible. A class
may have properties and variables that are used only internally, and that don't
need to be exposed publicly. In such cases you can declare a member to be private.
Note: If you've used other
languages such as Java or C# then you should note that a private member in
ActionScript 2.0 behaves like a protected member in Java or C#.
In order to declare a member as public or private you can use the public
and private
keywords, respectively. For example, the following declares a private property:
private var _nInterval:Number;
By convention you can use the underscore character as the first character
in a private property's name to help differentiate between local variables,
parameters, and private properties within the class.
We'll take a look at declaring public and private members in context within
an upcoming section. An example of private and public members should help
to clarify this topic, and in an upcoming section you'll create a custom class
that uses both public and private members.
Note: If you don't specify either public or private then the
default is public.
Understanding Static Members
Static members are members that are accessed directly from the class, and
not from instances. This is not a new concept to ActionScript 2.0. In fact,
since Flash 5 you have seen built-in classes with static members. For example,
the Math class
is comprised entirely of static members. Rather than creating an instance of
the Math class
and then accessing the properties and methods from a instance, you always access
the properties and methods directly from the class itself. For example:
trace(Math.cos(3.14));
Notice that the cos()
method is accessed directly from the Math
class, thus it is a static method.
In order to create a static member in an ActionScript 2.0 class you use the
static keyword
in the declaration. And static members can be further modified to be either
public or private, just like non-static members. Here's an example of a public
static member declaration.
public static var classname = "Car";
Declaring a Class
If we look at a class structure in very simplistic terms, there are four basic
parts:
* The class declaration consisting of the keyword class
and the name of the class.
* Property declarations.
* Constructor declaration.
* Method declarations.
Let's examine each of these parts a little more closely:
Class declaration
To declare a class you use the keyword class
followed by the name of the class. Then you enclose the class definition in
curly braces. For example:
class Car
{
// Class definition.
}
If you want to place the class in a package then you need to indicate the package
as part of the class name in the declaration. We call the name of a class that
includes the package the fully-qualified class name. For example, if you wanted
to place the Car
class in the package com.person13,
then the class declaration would look like this:
class com.person13.Car
{
// Class definition.
}
And, of course, when you place a class in a package, you must be sure to save
the class file to the corresponding directory. In the case of the com.person13.Car
class the file Car.as should be saved in a directory structure of com/person13
where the com directory is located within the Flash classpath. (For example,
if your classpath includes D:\ActionScriptClasses, then you could save the file
as D:\ActionScriptClasses\com\person13\Car.as.)
Property Declarations
You must declare all properties within the curly braces of a class definition.
You must also declare all properties outside of any methods. By convention you
should declare all the properties at the top of the class definition. For example:
class com.person13.Car
{
private
var _sMake:String;
private var _sModel:String;
private var _nYear:Number;
private var _nMiles:Number;
private var _nInterval:Number;
// Rest
of class definition.
}
Constructor Declaration
After you've declared the properties within the class, you should next declare
the constructor. Technically, if you don't declare a constructor explicitly,
Flash will create an implicit empty constructor for you. But even if your constructor
does not do anything, it is still good form to declare the constructor explicitly.
Remember, the constructor is a special method that shares the same name as the
class. The constructor can be used within a new statement to create new instances
of the class. The constructor should be declared just like a regular function,
and even though it can accept parameters, it should not return any values. Here's
an example of the Car
class with a constructor:
class com.person13.Car
{
private
var _sMake:String;
private var _sModel:String;
private var _nYear:Number;
private var _nMiles:Number;
private var _nInterval:Number;
function
Car(sMake, sModel, nYear, nMiles) {
_sMake
= sMake;
_sModel = sModel;
_nYear = nYear;
_nMiles = nMiles;
}
//
Rest of class definition.
}
Unlike some other languages, you cannot have overloaded constructors in ActionScript
2.0.
Declaring Methods
Next you can declare the methods of your class. You declare methods just like
standard functions, using the function
keyword and the same exact syntax. Remember, a method is a function, but it
is associated with a class. Because you declare the function within the class,
Flash automatically knows to associate it with the class. The only differences
between standard functions and methods are that you can declare methods to be
public, private, and static if appropriate. Here's an example of the same Car
class with two methods - one public and one private.
class com.person13.Car
{
private
var _sMake:String;
private var _sModel:String;
private var _nYear:Number;
private var _nMiles:Number;
private var _nInterval:Number;
function
Car(sMake, sModel, nYear, nMiles) {
_sMake
= sMake;
_sModel = sModel;
_nYear = nYear;
_nMiles = nMiles;
}
public
function drive(nMPH:Number):Void {
if(nMPH
== null || nMPH == 0) {
clearInterval(_nInterval);
}
else {
_nInterval
= setInterval(this, "increment", 1000, nMPH);
}
}
private
function increment(nMPH:Number):Void {
_nMiles
+= nMPH;
}
}
Working with Getter/Setter Methods
Getter and setter methods are special methods that are accessible outside
the class as properties, but are defined within the class as methods. Among
the potential advantages of getter and setter methods is that these methods
allow you to create members that work like properties external to the class,
but that can have sophisticated logic built into them. In the case of our Car
class example, we might want to make sure that the value for the year of the
car is never set earlier than 1886 (the year the first automobile was invented)
and that the number of miles is never set less than 0. Additional benefits of
getter and setter methods are:
* They allow us to work with property names such as _nMiles
within the class, but to expose the values publicly with more user-friendly
property names such as miles.
* They allow us to create read-only and write-only properties.
* They allow us to create virtual properties - properties that don't correspond
to any one property within the class, but that are generated based on a mixture
of internal values.
A getter method should never accept any parameters and should always return
a value. The syntax for a getter method is as follows:
function get
externalPropertyName():ReturnType {
// Method
definition, including return statement.
}
The method can, like other methods, be modified with the public
and static keywords as well, but you may not declare
a getter method as private.
Here's an example of a simple getter method that returns the value of _nMiles
as the property miles.
public function get miles():Number {
return _nMiles;
}
Setter method syntax is very similar to the syntax for a getter method except
that it should always accept a parameter, never return a value, and use the
set keyword instead
of get. Here's
the basic syntax:
function set externalPropertyName(parameterName:DataType):Void
{
// Method
defintion.
}
And just like getter methods, you can modify setter methods with the public
and static keywords,
but not with private.
Here's an example of a setter method that assigns a new value to the private
property _nMiles.
Notice that it checks to make sure the value is 0 or greater. If not, it uses
the default value of 0.
public function set miles(nMiles:Number):Void {
if(nMiles
>= 0) {
_nMiles
= nMiles;
}
else {
_nMiles
= 0;
}
}
Importing Classes
When you place classes in packages, you need to always use the fully-qualified
class name when you reference the class. That means that if you have created
com.person13.Car,
then in order to create an instance of the class your constructor statement
might look something like this:
var car:com.person13.Car
= new com.person13.Car("Oldsmobile", "Alero", 2000, 43000);
There is, however, a shortcut. You can use the import
statement to tell Flash what packages and classes you want it to know about
without having to specify the package. Then, Flash will automatically assume
the package name without you having to specify it each time. Here is an example
that imports the Car
class and then constructs an instance.
import com.person13.Car;
var car:Car = new Car("Oldsmobile", "Alero", 2000, 43000);
You'll notice that it is much more readable. Also, when you have many references
to the class name, it can save you a lot of time typing.
You can also import all the classes in a package using the *
wildcard. For example, the following will import any class in the com.person13
package.
import com.person13.*;
Creating a Class
You've had a chance to now see some of the preliminary stuff with regard to
ActionScript 2.0 classes, but I can tell you're ready to jump in and create
a class of your own. We'll start out by creating a class named Car.
Just follow the steps that follow:
1. Open a new ActionScript file. If you use Flash MX Professional 2004 then
you can use the ActionScript file editor that is in the IDE. Otherwise, you
can use your favorite text editor so long as it can save a plain text file.
2. The first code you should add to the file is the class declaration. In order
to do this you use the class keyword followed by the class name and then curly
braces to surround the class definition. So start by adding the following code
to your file:
class com.person13.Car {
}
3. Next declare the five properties. You'll make each of these properties
private. The first four should be fairly self-evident. The last property you'll
use to store the interval ID for an interval method you'll set in one of the
methods.
class com.person13.Car
{
private
var _sMake:String;
private var _sModel:String;
private var _nYear:Number;
private var _nMiles:Number;
private var _nInterval:Number;
}
4. Then declare the constructor. In this case, let's have it accept four parameters
and assign those values to the corresponding properties. You'll notice that
in two cases we're referencing properties that we didn't declare. That's because
those two properties will be defined with setter methods shortly. We want to
set the setter methods in those cases because we want to employ some logic that
makes sure the values are valid.
class com.person13.Car
{
private
var _sMake:String;
private var _sModel:String;
private var _nYear:Number;
private var _nMiles:Number;
private var _nInterval:Number;
function
Car(sMake, sModel, nYear, nMiles) {
_sMake = sMake;
_sModel = sModel;
year = nYear;
miles = nMiles;
}
}
5. Next, declare some methods for the class. In this case we'll create a single
public method named drive().
Then, we'll also create a private method named increment()
that will get called on an interval once the drive()method
has been called with a valid miles per hour parameter.
class com.person13.Car
{
private
var _sMake:String;
private var _sModel:String;
private var _nYear:Number;
private var _nMiles:Number;
private var _nInterval:Number;
function
Car(sMake, sModel, nYear, nMiles) {
_sMake
= sMake;
_sModel = sModel;
year = nYear;
miles = nMiles;
}
public
function drive(nMPH:Number):Void {
if(nMPH == null || nMPH <= 0) {
//
If nMPH is null or less than or equal to 0 then
// we want to tell the car to stop
// driving…We can do that by clearing the interval.
clearInterval(_nInterval);
}
else {
//
Otherwise, if nMPH is a number in the valid
// range, then set an interval so
// that the private method increment() is called
// once a second or so.
_nInterval = setInterval(this, "increment", 1000, nMPH);
}
}
private function increment(nMPH:Number):Void {
// Each
time the method is called, update the _nMiles value
// by incrementing it by nMPH. Of course, since the method
// is called once a second, the actual mileage increment is
// about 360 times what it would be. But, hey, we've
// got to speed things up a bit so that we can see some
// progress within a short amount of time. ;)
_nMiles += nMPH;
}
}
6. The remaining step is to define the getter and setter methods as shown
in the following code:
class com.person13.Car
{
private
var _sMake:String;
private var _sModel:String;
private var _nYear:Number;
private var _nMiles:Number;
private var _nInterval:Number;
function
Car(sMake, sModel, nYear, nMiles) {
_sMake
= sMake;
_sModel = sModel;
year = nYear;
miles = nMiles;
}
public
function get make():String {
return _sMake;
}
public function get model():String {
return _sModel;
}
public function get year():Number {
return _nYear;
}
public function set year(nYear:Number):Void {
if(nYear >= 1886) {
_nYear = nYear;
}
else {
_nYear = 1886;
}
}
public function get miles():Number {
return _nMiles;
}
public function set miles(nMiles:Number):Void {
if(nMiles >= 0) {
_nMiles = nMiles;
}
else {
_nMiles = 0;
}
}
public
function drive(nMPH:Number):Void {
if(nMPH
== null || nMPH <= 0) {
clearInterval(_nInterval);
}
else {
_nInterval
= setInterval(this, "increment", 1000, nMPH);
}
}
private
function increment(nMPH:Number):Void {
_nMiles
+= nMPH;
}
}
7. If you haven't yet done so, create a com/person13 directory within your
Flash classpath. For example, if your classpath includes D:\ActionScriptClasses,
then make sure you have created D:\ActionScriptClasses\com\person13.
8. Save the ActionScript class file as Car.as to the com/person13 directory.
9. Open a new Flash document (.fla).
10. On the first frame of the main timeline add the following ActionScript code:
import com.person13.Car;
//First, a function that will display the miles property value
// for a Car object.
function displayMileage(carObj:Car):Void {
trace(carObj.miles);
}
// Create the Car object.
var car:Car = new Car("Oldsmobile", "Alero", 2000, 43000);
// Tell the car to start driving at 65 miles per hour (for those of you
// outside of the U.S., you'll have to work out the conversions to
// kilometers yourself! ;)
car.drive(65);
// Set an interval so that the mileage of the Car object will
// continually display.
setInterval(displayMileage, 100, car);
11. Test the movie.
You should see the mileage of the car displaying in the Output panel. It should
increment by 65 once a second or so.
Conclusion
In this article I touched on the basics of ActionScript 2.0 classes. I didn't
yet go into the details of extending classes or implementing interfaces. We'll
save those topics for a third installment on account of this article is already
long enough. Thanks for reading.
READ PART THREE.
visit joey's site here.
Talk about ActionScript 2.0 ON THE FLASH MX 2004 FORUMS.
|