flash native_classes_value
The value of extending native classes
In the previous chapter we discovered the key concepts for object oriented programming. One of the mains difficulties of this often comes in putting these concepts into practice in real ActionScript projects.
The great power of Flash lies in its capacity to link design and programming. We will now look at this link to put into practice what we have learned in the previous chapter.
The concept of inheritance is not limited to personalized classes and can be applied to any API class in the Flash player. It is for example possible to extend the native MovieClip class by defining new methods in order to obtain an improved MovieClip.
The goal of this chapter is to learn and extend native classes such as MovieClip, Sprite, BitmapData but also non graphic class such as array in order to increase the functionalities offered by it.
Beware, we can see that certain native classes are considered as sealed and cannot be extended.
Our old friend the prototype
In ActionScript 1, developers were used to using the prototype of a class in order to increase its capabilities. In ActionScript 3 this practice still works but is not officially recommended.
In the following code we define a hello method on the prototype of the MovieClip class:
// adding a hello method MovieClip.prototype.hello = function () { // displays : [object MovieClip] trace( this ); } // creation of a clip var myClip:MovieClip = new MovieClip(); // the clip automatically has the method added to the prototype myClip.hello();
The clip created automatically has the hello method. Even though it is effective, this technique pollutes the other instances of the same class, as the hello method is available on all MovieClips of the animation.
In the following code we call the Hello method on the main timeline:
// adding a hello method MovieClip.prototype.hello = function () { // displays : [object MainTimeline] trace( this ); } // the timeline automatically has the method added to the prototype this.hello();
In an inheritance context, the idea is to obtain a new object type, to provide new functionalities. By using this technique we cannot create a new object variety, we simply add functionalities to an existing class.
Imagine that we need to create a ball with the ability to bounce in an elastic way. We could define all the necessary collision methods for our ball on the prototype of the MovieClip class, but would it be optimised?
By using this approach, all the MovieClips of our application would be provided with rebound capability. It would be more interesting to extend the MovieClip class and to link our ball to the sub-class. On the other hand, the prototype has major value due to its simplicity and efficiency. Let’s take the case of the DisplayObjectContainer class.
As we have seen in the chapter entitled The DisplayList, the DisplayObjectContainer class doesn’t define the method allowing us to delete all of the child objects. Using the method added to the prototype of the DisplayObjectContainer class we can very easily add this functionality:
DisplayObjectContainer.prototype.removeChildren = function ( ) { var numChildren:int = this.numChildren; while ( this.numChildren > 0 ) this.removeChildAt ( 0 ); return numChildren; }
All of the instances of the DisplayObjectContainer class have a removeChildren method. As well as allowing the deletion of all children, this returns the number of deleted children.
If we have multiple graphic objects on the main timeline we can delete them by calling the removeChildren method:
DisplayObjectContainer.prototype.removeChildren = function ( ) { var numChildren:int = this.numChildren; while ( this.numChildren > 0 ) this.removeChildAt ( 0 ); return numChildren; } // delete all child objects from main timeline this.removeChild();
In the same way we can delete all child objects from an instance of the Sprite class:
// creation of a Sprite type container var mySprite:Sprite = new Sprite (); // creation of child shape object var myShape:Shape = new Shape(); myShape.graphics.lineStyle ( 1, 0x990000, 1 ); myShape.graphics.beginFill ( 0x990000, .2 ); myShape.graphics.drawCircle ( 50, 50, 50 ); mySprite.addChild( myShape ); addChild ( mySprite ); // deletion of child objects var numChildrenRemoved:int = mySprite.removeChildren();
When testing the previous code a compilation error is generated:
1061: Call to a possibly undefined method removeChildren through a reference with static type flash.display:Sprite.
The compiler prevents the compilation as no removeChildren method is found. In order to quiet the compiler we can exceptionally cast the dynamic Object class so that is not submitted to type verification on compilation:
// creation of a Sprite type container var mySprite:Sprite = new Sprite (); // creation of child shape object var myShape:Shape = new Shape(); myShape.graphics.lineStyle ( 1, 0x990000, 1 ); myShape.graphics.beginFill ( 0x990000, .2 ); myShape.graphics.drawCircle ( 50, 50, 50 ); mySprite.addChild( myShape ); addChild ( mySprite ); // deletion of child objects var numChildrenRemoved:int = Object(mySprite).removeChildren(); // displays : 1 trace( numChildrenRemoved );
We will come back to the value of prototyping in the chapter entitled The text.
Worth remembering
- The use of a prototype is still possible in ActionScript 3.
- Its use is officially advised against but offers flexibility for certain precise cases.
- We prefer in the majority of cases the use of sub-classes in order to extend capabilities.
Mediabox Training Centre © 2000 - 2008 All rights reserved.
Adobe Authorized Training Centre. State convention under number 25 14 02167 14.
Mediabox : SARL au capital de 62.000€ - Activity number: 25 14 02167 14 - SIRET : 493 716 468 00027
MEDIABOX, 102 Avenue des Champs Elysées, 75008 PARIS - Tel. +33(0)2.31.91.96.89 - Fax. +33(0)2.72.68.56.42


