Tuesday, January 8, 2008

Next! - Inheritance

Hi again, today i am hereto talk about inheritance and object extenders.

Inheritance is one thing we have from Java and other OOP languages, its about to create a class based on other class, in Javascript we dont have classes and obvious no class inheritance.

So what most people use? Object extenders! When i first found it i thought it was great and i did myself a small class system with support to extent classes, implement other objects and specify creators, constructors etc...

It was great but after doing some classes and some other classes extending base classes etc, i noticed that the execution was slow, there was a loose in extending objects so i just quited it ( also lost sources... )

So if we look to a library like PrototypeJS, we notice that they use way too much object extenders.

So what is a object extender? Lets see how PrototypeJS does it:
Object.extend = function(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
return destination;
};
Thats it! It will iterate over all methods and properties of an object and include them in other object.
Is this bad? Well we cant say that it is much bad, theres times that we really need to use it, theres no other choice, so we use it to make our life easier.
So where should we not use it? If we look at PrototypeJS we see some:
Object.extend(String, {
interpret: function(value){
return value === null ? '' : String(value);
}
});
Object.extend(String.prototype, {
startsWith: function(pattern){
return this.indexOf(pattern) === 0;
},
endsWith: function(pattern){
var d = this.length - pattern.length;
return d >= 0 && this.lastIndexOf(pattern) === d;
},
empty: function(){
return this === '';
},
blank: function(){
return (/^\s*$/.test(this));
}
});
As you can see, they are extending core functions as i stated on my last post, but they are using Object.extend for it, so they create a new object, iterate over it and extends the core functions.
So even if we don't use any of these extensions to String there was a small loose time for Inheritance over the objects.
The right approach would be:
String.interpret= function(value){
return value === null ? '' : String(value);
};
String.prototype.startsWith= function(pattern){
return this.indexOf(pattern) === 0;
};
String.prototype.endsWith= function(pattern){
var d = this.length - pattern.length;
return d >= 0 && this.lastIndexOf(pattern) === d;
};
String.prototype.empty= function(){
return this === '';
};
String.prototype.blank= function(){
return (/^\s*$/.test(this));
};
I don't know if they do that for look better or for saving type same thing over and over or for save some kb (faster downloading, slower parse...)
The truth is that its a bit hard to be typing same thing over and over and also it takes some extra space, we can do a simple workaround:
(function(){
var S=String, Sp=S.prototype;
S.interpret= function(value){
return value === null ? '' : String(value);
};
Sp.startsWith = function(pattern){
return this.indexOf(pattern) === 0;
};
Sp.endsWith= function(pattern){
var d = this.length - pattern.length;
return d >= 0 && this.lastIndexOf(pattern) === d;
};
Sp.empty= function(){
return this === '';
};
Sp.blank= function(){
return (/^\s*$/.test(this));
};
})();
Easier to type and we save some kb. I wrapped it around a function cause i don't want to populate the global scope. This function can be the same for wrap all our code.

So far we stated the no need to use object extenders to extend core functions, but it is the same for lib functions
In PrototypeJS we do ( it changed on new version, but on background its the same ):
var MyClass=Class.create();
Object.extend(Myclass,{
staticVar:10
});
Object.extend(Myclass.prototype,{
Var:10,
otherVar:15,
initialize:function(v){
this.Var=MyClass.staticVar+v;
}
});
This is the same as:
var MyClass=function(v){
this.Var=MyClass.staticVar+v;
};
MyClass.staticVar=10;
MyClass.prototype.Var=10;
MyClass.prototype.otherVar=10;
The diferences are that in first code we do 2 object extends ( wish means iteration etc... ) but we have a nicer code wish is simpler to type, in the second one theres no call to any extender but it looks worse because we keep typing same thing over and over
We can use the same method as we did before ^^ to make the var names smaller etc

I hope no one thinks that i hate PrototypeJS etc... I don't! I used it lots of times for lots of different projects and it is a great library, but it fails at some points, nothing its perfect, and one of this points is the over-use of object extenders

Now how will i do my classes etc on Next! library? First i will extend core objects ( prototyping obvious ) and i will put my classes on context "next". eg.: next.Animator

And also it will suport classes that extend other classes, yes, but using a diferent method
Function.prototype.Extends=function(baseClass){
function Inheritance(){}
Inheritance.prototype = baseClass.prototype;
this.prototype = new Inheritance();
this.prototype.constructor = this;
if (baseClass.base) {
baseClass.prototype.base = baseClass.base;
}
this.parentClass=baseClass;
this.base = baseClass.prototype;
};
Remember the "MyClass" that i created before, lets say i want to create another class based on it:
var MyOtherClass=function(v,c){
this.base.constructor.call(this,v+c);//calls super constructor
};
MyOtherClass.Extends(MyClass);
I'm out of time to explain this better but you can have a light of what it is, although its supported i don't think i will use it much times.

Its all for now!!

No comments: