Mootools "Extends" plus "Implements"
I like to write my code slim and sexy (on the performance and memory side), I am using Mootools and was wondering if I was using it the correct way, also you can help me by telling me how to test my c开发者_JAVA百科ode to find the answers I am looking for my self.
//First we create a class like so:
var FirstClass = new Class {(
'someFunc': function() { /* do stuff */ }
})
//Now this class uses first class with "Implements"
var SecondClass = new Class ({
'Implements': [FirstClass, SomeOtherClass, SomeOtherOtherClass],
'iAlsoDoStuff': function() {/*do stuff */}
})
// finally the class that Extends second class
var ThirdClass = new Class ({
'Extends': SecondClass,
'takeOverTheWorld': function() {/*code to win lottery */}
})
How can I tell if every time secondclass is extended it doesnt make a new copy of the Implemented classes? The reason I am doing what I am doing above is to Extend SecondClass for every class that needs it - doing so statically, while the second class cannot extend more then one class thus I am using Implements.
The main difference between Extends and Implements is that Implement changes the class's prototype, while Extend creates a copy. This means that if you implement a change into a class all instances of that class will inherit that change instantly, while if you use Extend then all existing instances will remain the same.
this is a quote from the mootorial, check it out. http://mootorial.com/wiki/mootorial/02-class/#implement-vs.-extend
as for the testing - I would very much recommend you build some sample cases with ninja classes and putting them on to http://www.jsfiddle.net - then ask for some analytical advice or the mootools mail list on google or on IRC (irc.freenode.net#mootools), SO does not seem to get many hits from the mootools core team. Ideally, you want to talk to somebody like aaron newton, arian, cpojer or rpflo :)
update: I even blogged about this but I was wrong. There simply is a difference in the order in which mutators like Extends
and Implements
are brought in. You can implement and extend but you need to declare Extends first for it to work.
Read more here: http://fragged.org/mootools-pattern-fun-class-implements-extends-at-the-same-time_1359.html
update Turns out, there are some cases where this is useful. Here is the problem:
var ninja = new Class({
kill: function() {
alert("kill!");
}
});
var human = new Class({
initialize: function(){
alert("i r human!");
}
});
var badass = new Class({
Implements: [ninja],
Extends: human,
initialize: function() {
alert("i r badass and.. ");
this.parent();
this.kill();
}
});
new badass(); // i r badass, i r human, this.kill is not a function exception.
... simply does not work. You need class human to implement ninja instead and class badass to simply extend human. Aside from the side-effect of humans getting a new kill method (which they may or may not know about), it will mean that badass will be able to use .kill as well as call upon his direct parent human.
Why not rewrite things the way you want them and w/o complications? Because you may be extending a native class like Request.JSONP and then decide to mixin a new storage class into your extended one. True story... Either way, you may not have the luxury of refactoring certain classes available to you.
An interesting pattern to overcome this (consider the human class your request.jsonp, defined elsewhere) - if you just want to add more methods and properties to the class you are extending but don't plan to reuse the mixin class (ninja):
human.implement(new new Class({
kill: function() {
alert("kill!");
}
}));
var badass = new Class({
Extends: human,
initialize: function() {
alert("i r badass and.. ");
this.parent();
this.kill();
}
});
new badass(); // // i r badass, i r human, kill!
Arguably, you could just do human.implement({ method: function });
but a class can be so much more.
If you want to have a saved reference to your ninja class for other uses, the above would would be the same as this (if you plan to reuse your mixin):
var ninja new Class({
kill: function() {
alert("kill!");
}
});
human.implement(new ninja);
// this is what differs from say - instantiation + shared inherited properties.
// also, a constructor will work.
// the alternative would just do:
// human.prototype.kill = function() { alert("kill"); }
var badass = new Class({
Extends: human,
initialize: function() {
alert("i r badass and.. ");
this.parent();
this.kill();
}
});
new badass(); // // i r badass, i r human, kill!
Hope this helps somebody. Here's a practical example where I am extending Request.JSONP with an additional storage class as a mixin: http://jsfiddle.net/dimitar/YacZe/
I finally got my answer on the Mootools google group, thought I would update it here in case some one finds interest in it.
http://groups.google.com/group/mootools-users/browse_thread/thread/5aec78813fa51cc1
Enjoy! Roman
Extends and Implements are very well tested by Mootools developers themselves. Infact the whole test suite they use is available on anutron/mootools-unittester. You don't need to be testing core functionality of the framework, its done for you (and done very well too).
I'd suggest having a good read up on what Extend and Implement do on the mootools docs, clientcide website, mootorial, etc.
How many objects are you creating by the way? If its not a huge number then memory etc. should not be a major issue even if it was creating the objects in a memory heavy manner. Could this be premature optimisation?
精彩评论