AS1 OOP: Prototypes
by senocular
Prototypes for Properties
Though the prototype object, though commonly used for
methods, is not solely for methods alone. Variable
properties of other more simple values can be defined there
as well. These can be variables that you wish consistent for
all object instances or also values to serve as defaults for
otherwise unique properties in objects.
An example of such a property as a default would be
Button and MovieClip objects’ useHandCursor property. By
default, each Button and Movieclip has a useHandCursor value
of true. This means when button actions such as onPress are
assigned to either a button or movieclip, the default arrow
cursor will change to a hand icon when the cursor is over
the button or movieclip. This true value is stored in the
button and movieclip prototypes and therefore is set for
each button and movieclip created.
When you want individual instances to have their own
useHandCursor value, you can just define a new useHandCursor
value for that instance itself. Properties defined directly
to object instances will have precedence over prototype
values. With this, realize that assigning a value to a
property which may not exist in an object instance but does
exist in the instance’s class prototype won’t mean that you
are assigning the value to that prototype variable. You
would actually then be creating a new variable specific to
the object that will then have precedence over the
prototype’s variable value when referenced for that object.
So a value referenced and a value assigned may not always be
the same variable. If you want a prototype value to change,
you will need to do so directly from the prototype object
itself, otherwise you would be defining a value in an
instance.
The following example will assume a movieclip called
clipA in the timeline.
- // trace default value for movieclips’ useHandCursor
- trace(MovieClip.prototype.useHandCursor); // traces
true
- trace(clipA.useHandCursor); // traces true
- // change the prototype and see it reflected in clipA
- MovieClip.prototype.useHandCursor = false;
- trace(MovieClip.prototype.useHandCursor); // traces
false
- trace(clipA.useHandCursor); // traces false
- // reset the prototype
- MovieClip.prototype.useHandCursor = true;
- trace(clipA.useHandCursor); // traces true
- // now set a unique useHandCursor for clipA that
overrides the prototype
- clipA.useHandCursor = false;
- trace(clipA.useHandCursor); // traces false
- trace(MovieClip.prototype.useHandCursor); // traces
true
When incorporating such defaults into your own classes,
be sure not to set anything for the value you wish to
default or it will override what is set in the prototype.
For example, using the house class, in defaulting the
siding, siding should only be set at all in the house
constructor if the siding is passed. When not, the prototype
value will be used.
- // class definition
- House = function(siding){
- this.floors = 4;
- if (siding != undefined){
- this.siding = siding;
- }
- };
- // default siding property value
- House.prototype.siding = "Red";
- // outputSiding method
- House.prototype.outputSiding = function(){
- trace(this.siding);
- };
- // create an instance of the House class
- myHouse = new House();
- myHouse.outputSiding(); // traces "Red"
Since no siding was passed in creating myHouse, the if
statement skipped the assignment of siding altogether in the
constructor. As such, the siding traced in the outputSiding
method is the siding referenced from the house prototype
object.
For an online collection of prototype functions, see
http://proto.layer51.com.