AS1 OOP: Custom Object Classes
by senocular
Static Properties and Methods
Sometimes you may need to handle properties or methods in a
class that is not specific to any instance of the class.
These are often kept in the class constructor function
object and are known as static properties and methods.
The Math object in Flash is an example of a "class" that
has static properties and methods. In fact, the Math object
is made solely of these. Never will you actually have a Math
instance; the only time you really use Math is when you need
to access its property values like Math.PI or its methods
like Math.round or Math.sin. All of these are static
properties and methods of the Math class. Each are defined
directly to the Math constructor (though since you never
make Math instances, the Math object is hardly a constructor
and technically thereby not seen so much as a class). Math
object methods, in their internal workings, really have no
reference to or make use of a this so much. Remember, this
in methods assigned in the constructor are used to reference
the calling instance. In a static Math method, this would
actually reference the Math object itself since Math is
playing the role of an instance in that case. Because Math
is a top level or global object, Math itself could be
directly referenced instead of a this, thereby reducing
confusion; something that could be a good idea when making
your own static methods.
- // access a Math static property
- trace(Math.SQRT2); // traces 1.4142135623731
- // run a Math static method
- trace(Math.sin(.5)); // traces 0.479425538604203
Maybe a better example of a class with a static method is
the String class. String instances all have access to normal
string methods such as charAt, substring, toLowerCase etc.,
but aside from those, the String constructor itself has its
own method, fromCharCode. This is a method that's called
directly from String itself, not an instance, and simply
creates a string from a single or a series of ASCII values.
Because it has no dependency on an existing string's value,
it has no need to be used from one. Basically, its a normal
function, it just makes a string so its kept within the
String constructor object.
- // make a string instance and use a string method
- myString = "Hello";
- trace(myString.substring(0,2)); // traces "He"
- // use a static string method from String itself which
- // creates a string instance, but isn't used on one
- myString = String.fromCharCode(72,101);
- trace(myString); // traces "He"
Static properties and methods can also be used to help
you with your custom classes. You can have them operate on
their own as the case is with the String object's
fromCharCode, or you can also use them in conjunction with
instances created by that class. One common use is in
counting how many instances of a class were created using a
static property to keep track of each instance made. All
you'd need to do is make a static property in the class
constructor called something like count. Then with each
constructor call, increment that value to update the number
of instances created. This can then be referenced directly
from the class constructor in the occasion you wish to know
how many instances of that class have been created. To
exemplify, lets make a new class, a Fish class.
- // define class constructor
- Fish = function(type){
- this.type = type;
- Fish.count++; // increment the count variable in
Fish
- };
- // define count in Fish to be 0 to start
- Fish.count = 0;
- // how many fish are there now?
- trace(Fish.count); // traces 0
- // make a new freshwater fish
- spot = new Fish("Freshwater");
- // how many fish are there now?
- trace(Fish.count); // traces 1
Because count is kept in the constructor itself and not
as a unique property of each fish instance, it will be
increased for each fish made reflecting the total number of
times the constructor is called.
In counting Fish, the Fish constructor function object
was referenced directly using "Fish." There are actually 2
other ways of accessing Fish from the constructor function
which could also be used. In my opinion, using the
constructor name directly is the best as its the most
straightforward, however, you also have the option of using
arguments.callee or through using the constructor property.
Expanding on this, we set up a class to keep track of all
instances created - even send them all events much in the
same way all movieclip's receive the onEnterFrame event.
This can be as simple as adding each instance to an array
property in the class constructor whenever the constructor
is called, though can also get more involved. This will be
covered in greater detail
later