Sunday, August 16, 2009

Prototype Programming

I have been playing with dynamic languages such as Ruby and Groovy. I like what I see so far. Also, I have been relearning JavaScript as a true dynamic language. I came across this concept called prototypical inheritance in JavaScript and it is fascinating. The idea of prototypical inheritance is to create a new object from an old object and then add "stuff" to it. Here is a simple JavaScript example:

// convenient method extracted from Douglas Crockford's
// website -
// http://javascript.crockford.com/prototypal.html
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}

var animal = {
name : "",
get_name: function () {
return this.name
}
};

var cat = Object.create(animal);
cat.name = "Mr. Black";
cat.says = "meow";

document.writeln(cat.name + " " + cat.says);

// Mr. Black meow


Instead of doing classical inheritance in static language such as Java, we simply add "says" method to the newly created cat object.

Interesting enough, there is way to achieve the same thing in Ruby:

animal = Object.new

def animal.name=(name)
@name=name
end

def animal.name
@name
end

cat = animal.clone
cat.name = "Mr. Black"

def cat.says
"meow"
end

puts cat.name + " " + cat.says # Mr. Black meow


Now, the "says" method is added to the cat object.

"class" does not exist in both JavaScript and Ruby. Everything is Object in JavaScript and Ruby.

It is possible to achieve the same thing in Java using AOP through Spring or AspectJ. But, we have to learn Spring or AspectJ first before integrating either of them into our application. Productive language like Ruby has this capability built in and developer can just use it without incurring huge upfront cost. I hope this is the first step to convincing some of my colleagues why using a productive language like Ruby or Groovy is important.

The usage of prototypical inheritance is unclear at the moment. But, reusing a chunk of code across objects is important. Usually, this is done through inheritance even though there is no "is-a" relationship. Deep inheritance can cause unnecessary complexity in our application. In Ruby, this problem can be solved using Module and Mixin.