Extends
Based on the fact that inheritance for objects is completely
controlled through __proto__ and __constructor__ a new means
of establishing inheritance can be formulated based on
manually altering these values. In describing each, these
values were both changed to demonstrate their role. Used
together, they can effectively define inheritance for an
object or class – an alternative methods of establishing
inheritance opposed to subclass.prototype = new superClass();
which, in effect, is just assigning __proto__ and
__constructor__ for the prototype in the first place.
Enter extends. Extends is a method for extending a class
given a new subclass which is to be derived from it.
Actionscript doesn’t already have an extends keyword or
method, but given your new-found knowledge of __proto__ and
__constructor__ and how they determine inheritance, one can
easily be made. All it would need to do is take one class
and make it inherit from another class, and what with?
__proto__ and __constructor__.
Because class constructors are functions, and the
foundation definition of a class, our new extends method can
be made as a prototype method of the Function object. That
way a class constructor can use it just as any other object
would use any of its methods. As a Function.prototype, the
extends method can then be used on a subclass to define a
__proto__ and a __constructor__ based on a passed super
class effectively defining the inheritance chain to that
super class. Here’s what you get.
this.prototype.__proto__ = superClass.prototype; //
for inheritance
this.prototype.__constructor__ = superClass; // for
super
};
// Use
subclass.extends(superclass);
What you have here is the defining of a class prototype’s
__proto__ and __constructor__ properties to point to a
correspoding prototype and constructor to represent a super
class. If you think about it, this is exactly what using
subclass.prototype = new superClass() is doing since the
super class instance will have a __proto__ to its class’s
prototype object and a __constructor__ to the class
constructor, only here a) you aren’t replacing the prototype
object and b) you don’t get properties of the super class
defined for the prototype object as specified in the super
class constructor.
The fact that you aren’t replacing the prototype object
when using extends is it’s big advantage. This allows you to
have defined values for your prototype before defining
inheritance. It also allows an easy means for changing
inheritance at run time without having to completely
re-define the class. On top of that, the fact that you
aren’t using a super class instance as prototype object
means you don’t run into that prototype instance issue when
attempting to keep track and count all instances of a
certain class that are in use.
The big disadvantage is that its not a standard. It works
just fine, it’s just that Macromedia suggests using
subclass.prototype = new superClass() to establish
inheritance. For more on Macromedia’s standards with OOP,
see their
standards whitepaper. That of course, stops few from
using it.
Now as extends exists here, its use is specific to
classes and class inheritance. Using the same concept, you
can also change the inheritance of class instances.
Instances, however, differ slightly in that they don’t
specifically use a __constructor__. The use of
__constructor__ is for super through prototype objects. With
instances, it’s the prototype object, or more specifically
__proto__, that determines that. So for instances, to
effectively change what an instance perceives to be it’s own
class, you would change its __proto__ property.
Object.prototype.setClass = function(class){
this.constructor = class;
this.__proto__ = class.prototype;
};
// Use
instance.setClass(class);
This method takes an instance and changes its class
association to be a new class – that of the class passed in
to the call. For all events and purposes for that instance,
in Flash, it’s considered an instance of that new passed in
class. Here, though, the issue of defined property values
becomes a little more relevant. Setting a class for an
instance this way won’t run the constructor for that
instance, just set up the inheritance chain for that
instance to follow the new class. You may want to call the
constructor for that instance if you want it to be
initialized, either in setClass or separately.
instance.setClass(class);
instance.constructor(constructor_arguments);
Where setClass comes especially handy is with movieclips.
Some of the shortcomings found in Object.registerClass can
be handled with this setClass method, most particularly for
defining a class association for pre-existing movieclips and
movieclips created with createEmptyMovieClip. Instead of
using Object.registerClass, just call setClass for your
movieclip and tell it what to be. Then that movieclip will
inherit all methods from that class’s prototype and be able
to use them as if it were initially created as an instance
of that class (remember to make the class a subclass of
MovieClip).
Example:
[ empty movieclip (triangle) dynamically given class ]