Bookmark this on Hatena Bookmark
Hatena Bookmark - enchant.js Succession and JavaScript Inheritance: The Subtle Differences
Share on Facebook
Post to Google Buzz
Bookmark this on Yahoo Bookmark
Bookmark this on Livedoor Clip
Share on FriendFeed

We’re about to release a WebGL-compatible version of enchant.js. Hope everyone gives it a try. With this in mind, I’d like to share something I noticed on Twitter the other day.

The Tweep was hitting a wall with enchant.js classes. Let’s see if we can’t sort out the confusion.

First of all, JavaScript class inheritance is called prototype base succession and is somewhat unique. For more on JavaScript class inheritance, check out this @IT article (in Japanese).

However, this type of prototype base inheritance may be a bit difficult to follow for people used to C++, Ruby, Java and other class base inheritance languages.

Reduced to the bare basics, prototype base refers to a method of constantly copying elements designated as .prototype.

To explain this, let’s review Java (class base) class definitions. You should get something like this:

//for Java
class A {
  int x;
  public A(){
    x=1;
  }
  public  int method(){
    System.out.println(x);
  }
}

//When using class
A a = new A();
a.method();

The name “JavaScript” may suggest a relationship to “Java,” but its prototype base approach to classes is completely different.

If you write a class with the same function in JavaScript, it should look something like this:

//for JavaScript
A = function(){
    this.x=1;
};
A.prototype.method = function(){
	document.write(this.x);
}

//When using class
var a = new A();
a.method();

This all may seem a bit baffling when compared to Java. The names are similar, but the contents are completely different.

But inheritance is even worse. Here’s what you get for inheritance in Java:

//for Java
class A {
  int x;
  public A(){
    x=1;
  }
  public  int method(){
    System.out.println(x);
  }
}

class B extends A {
  int y;
  public B(){
    super(); //Calls up parent class constructor
    y=100;
  }
  public  int anotherMethod(){
    System.out.println(x*y);
  }
}

//When using inherited class
B b = new B();
b.method(); //Calls up parent class
b.anotherMethod(); //Calls up inherited class method

The inheritance class is defined by the keyword “extends.” The A and B class definitions are clearly delineated, making them easy to understand upon a brief glance.

If you’re used to this, JavaScript inheritance may seem rather unusual.

A = function(){
    this.x=1;
};
A.prototype.method = function(){
	document.write(this.x);
}

B = function(){
    A.call(this); //Calls up parent class constructor
    this.y=100;
}
B.prototype = new A(); //Inherited here
B.prototype.anotherMethod = function(){
	document.write("<BR>"+this.x*this.y);
}

var b = new B();
b.method();
b.anotherMethod();

The inherited area actually inserts the newly created A (class to be inherited from) object into B.prototype.

In the case of JavaScript, the fact that an interpreter language, not a compiler language, is at work is key in this inheritance model.

In JavaScript, the member designated in the prototype properties are automatically copied when creating a new instance by a new operator.

In inheritance, the parent class information is copied wholesale by the child class (not “copied” in the strictest sense, but implicitly based upon. Please see the @IT article for more information). This is JavaScript’s basic method for inheritance.

From the perspective of processing (JavaScript) implementation, this allows extremely easy class inheritance. No matter what, all you need to do is copy.

There’s also no need of a special syntax to define classes or inheritance.

On the other hand, we can cite the lack of a suppressor tool held by object orientation (all members are public) as a defect.

This is a significant obstacle in trying to write large programs. Anyone can rewrite the basic programming language at any time to suit their wishes.

For instance, there are built-in arrays in JavaScript, but one can add or alter array functions themselves whenever they like.

Array.prototype.remove=function(obj){ //Adds "remove" method to delete arbitrary elements of an array
	for(i = 0; i < this.length; i++){
 		if(this[i] === obj){
 			this.splice(i,1);
		}
	}
}

var hoge = [1,2,3,4];

hoge.remove(3);

for(i=0;i<hoge.length;i++)
	document.write(hoge[i]+','); //Displays contents of array

In the above code we added added an example method, “remove,” to a preexisting class where it will arbitrarily delete elements of an array.

So why does JavaScript use this peculiar prototype inheritance system?

We can propose various reasons for this, but the bottom line is that prototype inheritance is extremely useful for writing compact, quick and dirty programs.

It’s easy to freely add or alter object members to suit one’s timing and needs.

We should note the difference here. Whereas in Java and other general class base languages the first-layer functions (treating functions on equal terms with variables) are not supported, in JavaScript they are supported.

Of course, if you have a good grasp of this and write a program with it, it’s fairly easy for the code to get very confusing very quickly. But if you get used to it you can achieve your programming goals with great ease and speed.

With that in mind, one must exercise caution when writing a JavaScript program with multiple programmers. You run the risk of intruding on similar code, or unintentionally brushing up against unrelated properties.

However, in the case of game programming, class base inheritance is in fact quite suitable. With that in mind, in enchant.js Class.create is included as a pseudo-support utility function for class base inheritance.

The usage of Class.create is extremely simple.

enchant(); //The enchant.js good luck charm

A = Class.create({       // Declares Class.create class
    initialize:function(){  //Constructor
        this.x=1;
    },
    method:function(){
        document.write(this.x);
    }
});

//Used in the same context as typical JavaScript
var a = new A();
a.method();

This jumble is where the literal expression of an object is delivered in Class.create.

In this way, at one glance, class definition along the lines of Java class declarations can be expressed. In the case of inheritance, you end up with something like what you see below.

enchant();。

A = Class.create({
    initialize:function(){
        this.x=1;
    },
    method:function(){
        document.write(this.x);
    }
});

B = Class.create(A,{   //Inherits A
    initialize:function(){
	A.call(this);  // Calls up A constructor
        this.y=100;
    },
    anotherMethod:function(){
        document.write(this.x*this.y);
    }
});

var b = new B();
b.method();
b.anotherMethod();

In this manner, you get a cleaner expression than by using prototype for inheritance. Even for programmers used to class base inheritance, this is a much easer-to-read code than using JavaScript prototype inheritance as is.

Moreover, because prototype base functions can also be used, you can write exciting code that could be tiresome to construct and full of unexpected difficulties in JavaScript.

For instance, each instance you can add methods with the same name that perform radically different functions.

enchant();

A = Class.create({
    initialize:function(){
        this.x=1;
    },
    method:function(){
        document.write(this.x);
    }
});

var m = [];
for(i=0;i<10;i++){
    var obj = new A();
    m.push(obj);
    switch( i % 4 ){
        case 0:
	    obj.method=function(){ //Rewrites method() with completely different contents
	        document.write("<BR>");
	    };
	    break;
        case 1:
	    obj.method=function(){ //Rewrites method() with completely different contents
	        document.write("booe");
	    };
        case 2:
	    obj.x=2
	    break;
    }
}

for(i=0;i<m.length;i++)
    m[i].method();

Neat, huh?

If we put this to practical use in game programming, we can define the basic enemy character class in Class.create, and just the precise movements of small fry characters with different contents under the same method name.

When calling up all you need to do is summon a single method name, so programming becomes vastly simpler.

Of course, even in class base languages, you can achieve this if you define a separate class corresponding to all the enemy character patterns, but there’s not a huge difference between the movements of small fry characters. So if you really need to *only* define the parts that are different, it’s smartest to use the platform base method.

In this way, if method and property names are the same, we refer to programming methods that *should* produce the same results as “duck typing.”

If you’re able to use this “duck typing” freely, you’ll be able to write code much more effectively than in programming languages where it is not possible.

This post may have been a bit tricky. What do you think? Did you follow us?