[partage] héritage de classes
Bonjour à tous. :-)
(mon premier poste)
J'ai décidé, il y a quelques jours, de créer de l'héritage en javascript. (juste pour le fun, car aucune utilité apparente.) J'ai donc commencé par chercher les différentes version existantes sur la toile mais celles que j'ai trouvé semblaient "mal" fonctionner. Je me suis donc dis que je pouvais m’atteler à la tâche sans craindre de refaire ce qui existe déjà.
Bref, voici mon code (qui devra certainement être amélioré).
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
function searchInArray(arr,elem) {
if (Array.prototype.indexOf) return arr.indexOf(elem);
for (var i in arr) if (arr[i] === elem) return i;
return -1;
}
function __uber(fname,arg){
var c = arguments.callee;
while(c.caller != null && typeof(c.caller.from)=="undefined")
c = c.caller;
if(c.caller!=null)
var parentIndex = searchInArray(this.constructor.herited,c.caller.from)-1;
else
var parentIndex = this.constructor.herited.length-1;
while(parentIndex>=0 && !this.parentFN[this.constructor.herited[parentIndex]] )
parentIndex--;
if(parentIndex < 0)
throw fname+"() not found in parent constructors of current object.";
var func = this.parentFN[this.constructor.herited[parentIndex]][fname] ;
var arg = arg || [];
return func.apply(this,arg);
}
function __construct(obj){
if(__construct.caller!=obj.constructor) return; // prevent from recursive calls
for(var i=0;i<obj.constructor.herited.length;i++){// for(var i in obj.constructor.herited) will call Array.prototype and Object.prototype functions
try{ obj.constructor.herited[i].apply(obj,__construct.caller.arguments); }
catch(err) { throw "error to calling parent constructor : "+i+" ["+err+"]"; }
try{ __copyFunctions(obj,obj.constructor.herited[i]); }
catch(err) { throw "error to copying parent functions of : "+i+" ["+err+"]"; }
}
}
function __copyFunctions(obj,constructorParent){
obj.parentFN = obj.parentFN || {};
obj.parentFN[constructorParent] = {};
for(var i in obj) if(typeof(obj[i])=='object' || typeof(obj[i])=='function'){
obj.parentFN[constructorParent][i] = obj[i];
obj.parentFN[constructorParent][i].from = constructorParent;
}
}
Function.prototype.inherits = function(Parent){
if(this.herited)
eval("var newF = "+this.toString()); // newF = clone( this ); -> change on newF.prototype will not affect this.prototype
else{
var s = this.toString();
var b = s.indexOf("{")+1;
eval("var newF = "+s.substring(0,b)+"__construct(this);"+s.substring(b,s.length));
}
for(var i in Parent.prototype)
newF.prototype[i] = Parent.prototype[i];
for(var i in this.prototype)
newF.prototype[i] = this.prototype[i];
newF.herited = (this.herited?this.herited.slice(0):[]);
var H = (Parent.herited?Parent.herited.slice(0):[]) // = parent.herited[]
H.push(Parent); // = parent.herited[] + parent
newF.herited = H.concat(newF.herited) // = parent.herited[] + parent + this.herited[]
newF.name = newF.name || this.toString().substring(9,this.toString().indexOf('(')); // define Function.name property for IE || it's useless
//\\ this.name = this.name || this.toString().substring(9,this.toString().indexOf('('));
//\\ if(this.name!="(") // the next line will don't work on unamed function
//\\ eval(this.name+" = newF"); // uncomment thoses lines to overwrite "this" function, then when you call B.inherits(A) that'll make : B = newF;
newF.prototype.uber = __uber;
return newF;
}; |
Et voici un bout de code pour le tester sommairement :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| var alert = function(val){document.write(val,"<hr>");};
function A(){this.a=1;this.aa=function(){alert("aa");};this.obj={val:97};this.hard=function(c){alert("a.hard: "+c);};}
A.prototype.fun = 11;
function B(name){this.b=2;this.bb=function(){alert("bb");};this.name=name;this.hard=function(v){alert("b.hard: "+v);this.uber("hard",arguments);};}
function O(){this.o=3;this.oo=function(){alert("oo");};}
function H(){this.h=4;this.aa=function(){alert("hh");};this.oo=function(){alert("hh");};}
H.prototype.fun = 22;
var B = B.inherits(A);
var H = H.inherits(B);
var H = H.inherits(O);
var h = new H("john smith");
alert("=============== FOR EACH IN ( h ) ===============");
for(var i in h) alert(i+": "+h[i]);
// a: 1
// b: 2
// o: 3
// h: 4
// func aa : alert hh
// func bb : alert bb
// func oo : alert hh
// parentFN : ############### object
// obj : object
// name : "john smith"
// uber : ############# function
// overwrited functions
alert("=============== OVERWRITED FUNCTIONS ===============");
h.aa(); // hh
h.oo(); // hh
alert("=============== SUPER/ORIGINAL FUNCTIONS ===============");
// super functions who been overwrited
h.uber("aa"); // aa
h.uber("oo"); // oo
alert("=============== HERITED FUNCTIONS ===============");
// herited function
h.bb(); // bb
alert("=============== OBJECTS FROM 2 DIFFERENT INSTANCES ===============");
// test if object1.obj != object2.obj
var h2 = new H();
h2.obj.val++;
alert(h2.obj.val); // 98
alert(h.obj.val); // 97
alert("=============== PARENTS PROTOTYPE AREN'T MODIFIED ON CHANGE OF CHILD PROTOTYPE ===============");
var a = new A();
alert(a.fun);
alert(h.fun);
alert("=============== FINAL TEST ===============");
h.hard("Happy End"); |
Voila, j'attend vos opinions avec impatience : Ca ne sert à rien ? Ca ne fonctionne pas ? Ca existe deja ? C'est une bonne idée à améliorer ? Suggestions ?
Bonne lecture et merci pour votre attention.
PS: code peu commenté mais j'ai essayé de le faire lisible .. puis y'a les tests pour le resultat. Car c'est ce qui compte in fine. :mrgreen: