AS1 OOP: Controlling OOP
         by senocular  

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.

Function.prototype.extends = function(superClass){
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 ]

 

Object.prototype.setClass = function(class){
this.constructor = class;
this.__proto__ = class.prototype;
};

 
Faller = function(ground){
this.ground = ground;
this.velocity = 0;
};
Faller.prototype = new MovieClip();
Faller.prototype.onEnterFrame = function(){
this.velocity++;
this._y += this.velocity;
if (this._y >= this.ground){
this._y = this.ground;
this.velocity *= -1;
}
};

 
this.createEmptyMovieClip("triangle", 1);
with (triangle){
// draw the triangle in the empty clip
// position
_x = 150;
_y = 20;
beginFill(0xaaaaaa, 100);
lineStyle(2,0,100);
moveTo(0,-10);
lineTo(10,10);
lineTo(-10,10);
lineTo(0,-10);
endFill();
}

 
// set the class
triangle.setClass(Faller);
// call the constructor to define ground property
triangle.constructor(100);

 

download source

 

Prev Page
 



SUPPORTERS:

kirupa.com's fast and reliable hosting provided by Media Temple.