Quantumwave Interactive Inc.
  Interactive media development . Programming . Design . Consulting

Different ways of inheritance in Flash 5 and Flash MX

There seems to be some confusion on which is the best way to set up inheritance in Flash. This article will try to explain the differences, and hopefully clear up the confusion.

The first part of this article deals with Flash 5. The second part deals with Flash MX. Japanese translation by FACEs can be found here.

In Macromedia's documentation, this is how inheritance is established:

	SubClass.prototype = new SuperClass();

What this line does is setting the prototype object of the SubClass to a new instance of the SuperClass. All properties and methods in the SuperClass instance are assigned to the SubClass's prototype chain - so all instances of SubClass will also be able to access these properties and methods.

Now, let's step back and take a look at SubClass (a constructor function) when it was defined before the previous statement. Whenever a function is defined (before it is even called), it is automatically given some properties.

One of those properties is the prototype object.

The prototype object has its own properties as well. The documented properties are: constructor and __proto__. The constructor property refers to SubClass itself, and __proto__ refers to the prototype object of the super class of SubClass.

Confused? No need - it is actually quite simple.

What is the super class of SubClass when it was defined? By default, all objects inherit from the super class Object (with a capital 'O'). Therefore, SubClass.prototype.__proto__ refers to Object.prototype.

So what happens to the prototype object of SubClass after the following statement?

SubClass.prototype = new SuperClass();

Both the constructor and __proto__ properties are overwritten with new values. What these new values are depend on the implementation. For example, in Flash 5 and JavaScript, constructor now refers to SuperClass, and __proto__ refers to SuperClass.prototype. However, the constructor of SubClass instances should be SubClass and not SuperClass.

	SubClass.prototype = new SuperClass();
	
	// the following two lines won't work in Flash 5 because of a bug
	// in comparing constructors, try it in Netscape instead
	trace(SubClass.prototype.constructor == SubClass);           // false
	trace(SubClass.prototype.constructor == SuperClass);         // true
	
	trace(SubClass.prototype.__proto__ == Object.prototype);     // false
	trace(SubClass.prototype.__proto__ == SuperClass.prototype); // true

Here are some of the issues with using 'new' for inheritance in Flash 5:

  1. the constructor property is incorrect (refers to the SubClass, not SuperClass)

  2.  
  3. invokes the SuperClass constructor to create an instance for inheritance.

    There are three side effects:

    a) extra memory is used to store a new instance of the superclass.

    b) it is against the idea of superclass/subclass relationship: the subclass is inheriting not from the superclass but from an instance of it.

    c) the superclass constructor is invoked unnecessarily. If a static property was used for keeping track of the number of times the superclass constructor has been invoked, or if the constructor attaches movieclips and increments a static variable for depths, the 'new' statement would mess it up. For example:
    	function SuperClass(x, y) {
    	   // Static (class) property
    	   SuperClass.invokeCount++;
    	
    	   this.x = x;
    	   this.y = y;
    	}
    	
    	SuperClass.invokeCount = 0;  // initialize static property
    	
    	SuperClass.prototype.superMethod = function() {
    	   trace("this.x"+ this.x +", this.y:"+ this.y);
    	}
    	
    	//------------------------------------------------------------------------
    	
    	function SubClass(x, y, z) {
    	   // inherit and initialize SuperClass's properties
    	   this.tmpBase = SuperClass;
    	   this.tmpBase(x, y);
    	   delete this.tmpBase;
    	
    	   this.z = z;
    	}
    	
    	trace(SubClass.prototype.__proto__ == Object.prototype);     // true
    	
    	SubClass.prototype = new SuperClass();
    	
    	trace(SubClass.prototype.__proto__ == Object.prototype);     // false
    	trace(SubClass.prototype.__proto__ == SuperClass.prototype); // true
    	
    	SubClass.prototype.subMethod = function() {
    	   trace("this.z"+ this.z);
    	}
    	
    	//------------------------------------------------------------------------
    	
    	var o = new SubClass('X','Y','Z');
    Now o.constructor == SuperClass, but it should be SubClass Also, SuperClass.invokeCount is 2 instead of 1.
     
  4. Flash 5 has a bug with using 'new' in which there are duplicated properties when using the FOR..IN loop.
  5. 	for (var p in o) {
    	   trace(p +":"+ o[p]);
    	}

    Output:
    -------
    subMethod:
    superMethod:
    y:Y
    x:X
    z:Z
    y:Y
    x:X

  6. If the 'new' statement is accidentally placed after the prototype definitions for that class, everything in the prototype are wiped out:
    	SubClass.prototype.subMethod = function() {
    	   trace("this.z"+ this.z);
    	}
    	
    	SubClass.prototype = new SuperClass();
    subMethod() is gone!


  In order to solve these problems, an alternative method can be used to inherit:

Change this line:

	SubClass.prototype = new SuperClass();

to:

	SubClass.prototype.__proto__ = SuperClass.prototype;

All the problems are resolved by changing this one line!

By setting the __proto__ property of SubClass to SuperClass's prototype, it sets up a link between SubClass and SuperClass. All the methods (and properties, if any) along SuperClass's prototype chain are now accessible through the prototype of SubClass This is basically how prototype-based inheritance works.

 

What about Flash MX?

Some of the issues listed above have been fixed in Flash MX:

  • The constructor property of a SubClass's instance is now correctly referring to the SubClass. However, SubClass.prototype.constructor is still referencing SuperClass if the 'new' syntax is used to set up inheritance.

  • The bug with duplicated properties in FOR..IN loops has been fixed.

  • Comparisons of the constructor property return correct results.


Some remaining issues in Flash MX when using 'new':

  • the constructor is, of course, still invoked unnecessarily when using 'new' for inheritance; limiting what can be put inside a constructor (for example: attaching movieclips and incrementing counters for depths and _x,_y locations will be messed up). One could write code to get around this problem inside the constructor; however, it makes the code more difficult to understand and creates more runtime overhead. Memory is still wasted as in Flash 5 with new instances of superclasses.

  • SubClass.prototype.constructor after using 'new' is still incorrectly referencing SuperClass.

  • If one uses __proto__ to establish inheritance, the super operator fails inside a constructor. Here are some solutions:

    • Use the traditional Flash 5 method of inheriting a superclass's properties instead of using super inside the constructor:
      this.tmpBase = SuperClass;
      this.tmpBase(args);
      delete this.tmpBase;
    • Use the extend() method (note that the word 'extends', with 's', is reserved for future use). It uses an undocumented property __constructor__; this method supports the use of super() in a constructor:
      Function.prototype.extend = function(superClass) {
         this.prototype.__proto__ = superClass.prototype;
         this.prototype.__constructor__ = superClass;
         ASSetPropFlags(this.prototype, ["__constructor__"], 1);
      };
      
      ASSetPropFlags(Function.prototype, ["extend"], 1);
      
      SuperClass = function(a) {
         this.a = a;
      };
      
      SubClass = function(a, b) {
         super(a);
         this.b = b;
      };
      
      SubClass.extend(SuperClass);


So which method should be used?

There is no doubt that using __proto__ is the better choice for Flash 5 because of the varies issues mentioned above.

In Flash MX, it is a tougher choice. Do you have to be compliant with the "standard"? Or would you rather avoid unnecessary overhead and wasted memory, by defining the relationships between classes directly along the prototype chain?


Working around these hidden surprises when using 'new'

  • If the constructor property is ever used, it can be manually reset to the correct constructor like this right after using 'new': SubClass.prototype.constructor = SubClass;

  • Know what to avoid inside a constructor when using inheritance. Or add code to by-pass initialization code in the constructor.

  • Try Branden Hall's protolink solution.


Reasons for using 'new'

Despite the issues mentioned above, I can think of two reasons for not using __proto__. You have to decide whether these are valid reasons for your own projects:

  • The __proto__ property is not in the ECMA-262 specifications.

    It is available in Netscape (JavaScript) but not in the newer Rhino (a Java coded version of JavaScript, which is also used in ColdFusion MX's .ASR Server-Side ActionScript) or SpiderMonkey (C++ version of JavaScript, also used in the Flash Communication Server's .ASC Server-Side ActionScript). It is also not available in Internet Explorer (JScript and JScript.Net). For code portability or for ECMA-262 standard compliance, __proto__ should be avoided.

  • Macromedia documentation, examples and their best practices whitepaper (pdf) promote the ECMA-262 standard.

    It is good practice to standardize on coding styles so code can be understood easily by other developers. For example, one solution is to encapsulate the inheritance method like this:

    SubClass.extend(SuperClass); // using the extend() method above


Any reason for using __proto__?

The __proto__ property is not depreciated in Flash MX. In fact, it is documented in both the ActionScript Dictionary and the Using Flash manuals. It is the most direct link between classes and objects along the prototype chain, and will likely be around in Flash for some time for backwards compatibility.

Another reason is not to waste memory storing instances of the superclasses just for inheritance. Define the relationships between superclass and subclass directly to form the prototype chain! This is especially important for larger projects with more complicated classes, or for smaller devices running with limited memory.

Because ActionScript is a prototype-based language, the idea of preventing the use of __proto__ doesn't make sense because the prototype and __proto__ depend on each other to form the prototype chain. If we're not supposed to use this property, it should be hidden like in JScript or ECMAScript, or make it read-only.

By the way, have you thought about why the constructor property is not read-only?


Where do we go from here?

To overcome the issues mentioned above, a class-based language would help. The closest example is Microsoft's JScript .Net, which is based on the ECMA-262 edition 4 proposal. It is available today, and works with both prototype and class-based objects and inheritance. The future of JavaScript (or ECMAScript) based on the edition 4 proposal is promising.

If you feel that ActionScript should head in this direction and implement class-based objects and inheritance, please send your vote to: wish-flash@macromedia.com.


See also
: Object Inheritance, Virtual MovieClip Class, Static Properties and Methods

Thanks to (alphabetically) Branden Hall, Colin Moock and Robert Penner for exploring and raising these issues with me during the Flash beta. You can read about these issues in all three of their books: OOP with ActionScript, ActionScript for Flash MX: The Definitive Guide, and Robert Penner's Programming Macromedia Flash MX. I highly recommend these books, not because I was the technical editor for both the OOP book and Robert's book, and beta reader for Colin's, but because these books stand out with valuable information for the hardcore ActionScript programmers.

Download source files: mxInheritance.zip (Flash MX format)

Previous Flash 5 demo: setInheritance.zip & setInheritance.sit

Last updated on: Nov 10, 2002 - Copyright © 2002 Dave Yang / Quantumwave Interactive Inc.

home | about | news | flash | director | shockwave | download | dave | résumé | contact

Copyright © 1995-2009 Quantumwave Interactive Inc.