ugrás a tartalomhoz

Javascript szülő osztály hívásának továbbörökítése

inf · 2010. Jan. 2. (Szo), 04.24
Üdv.

Van egy kis gondom, amire nem találtam semmilyen megoldást.
A lényeg, hogy származtatni szeretnék osztályokat egymásból, és a szülő osztály függvényeit elérni. A gondom az, hogy a szülő osztályból hívott függvényben a this.parent nem a nagyszülőre, hanem a szülőre vonatkozik, és így végtelen ciklusba kerül. Ez persze logikus, viszont kíváncsi vagyok létezik e megoldás ennek kikerülésére.

Itt egy példa:
  1. Object.prototype.extend=function (source)  
  2. {  
  3.     if (source)  
  4.     {  
  5.         for (var property in source)  
  6.         {  
  7.             if  
  8.             (  
  9.                 (property in Object.prototype)  
  10.                 ?  
  11.                     source[property]!==Object.prototype[property]  
  12.                 &&  
  13.                     this[property]===Object.prototype[property]  
  14.                 :  
  15.                     !(property in this)  
  16.             )  
  17.             {  
  18.                 this[property]=source[property];  
  19.             }  
  20.         }  
  21.     }  
  22.     return this;  
  23. };  
  24.   
  25. Object.prototype.implement=function (source)  
  26. {  
  27.     if (source)  
  28.     {  
  29.         for (var property in source)  
  30.         {  
  31.             if  
  32.             (  
  33.                 !(property in Object.prototype)  
  34.             ||  
  35.                 source[property]!==Object.prototype[property]  
  36.             )  
  37.             {  
  38.                 this[property]=source[property];  
  39.             }  
  40.         }  
  41.     }  
  42.     return this;  
  43. };  
  44.       
  45. Class=function (source)  
  46. {  
  47.     return function ()  
  48.     {  
  49.         if (this.initialize instanceof Function)  
  50.         {  
  51.             this.initialize.apply(this,arguments);  
  52.         }  
  53.     }.implement(source);  
  54. };  
  55.   
  56. Function.prototype.extend(  
  57. {  
  58.     extend: function (source)  
  59.     {  
  60.         this.prototype.extend(source.prototype);  
  61.         this.prototype.parent=source.prototype;  
  62.         return this;  
  63.     },  
  64.     implement: function (source)  
  65.     {  
  66.         this.prototype.implement(source);  
  67.         return this;  
  68.     }  
  69. });  
  70.       
  71. var a=new Class(  
  72. {  
  73.     initialize: function ()  
  74.     {  
  75.         this.a=1;  
  76.     }  
  77. });  
  78.   
  79. var b=new Class(  
  80. {  
  81.     initialize: function ()  
  82.     {  
  83.         this.parent.initialize.apply(this,arguments);  
  84.         this.b=1;  
  85.     }  
  86. }).extend(a);  
  87.   
  88. var c=new Class(  
  89. {  
  90.     initialize: function ()  
  91.     {  
  92.         this.parent.initialize.apply(this,arguments);  
  93.         this.c=1;  
  94.     }  
  95. }).extend(b);  
  96.   
  97. var d=new c;  
  98. alert(d.a && d.b && d.c);  
 
1

BUÉK

toxin · 2010. Jan. 2. (Szo), 13.08
első blikkre szvsz ott lehetne egyszerűen megfogni,hogy a parent hívásokat
  1. this.parent.initialize.apply(this,arguments);   
függetlenítjük a this-től, azaz a parent-et, a konstruktor függvények - mint objektumok - tagváltozójává tesszük >
  1.  Function.prototype.extend(    
  2.  {    
  3.      extend: function (source)    
  4.      {   
  5. //...  
  6.  this.prototype.parent=source.prototype;    
  7. //...  
helyett :
  1.  Function.prototype.extend(    
  2.  {    
  3.      extend: function (source)    
  4.      {   
  5. //...  
  6.  this.parent = source.prototype;   
  7. //...  
a kód első feléhez nem nyúltam, a második fele :
  1. Function.prototype.extend({  
  2.     extend: function(source){  
  3.         this.prototype.extend(source.prototype);  
  4.         this.parent = source.prototype;  
  5.         return this;  
  6.     },  
  7.     implement: function(source){  
  8.         this.prototype.implement(source);  
  9.         return this;  
  10.     }  
  11. });  
  12.               
  13. var A = new Class({  
  14.     initialize: function(){  
  15.         this.a = 1;  
  16.     },  
  17.       
  18.     getA : function(){  
  19.         return this.a;  
  20.     }  
  21. });  
  22.   
  23. var B = new Class({  
  24.     initialize: function(){  
  25.         B.parent.initialize.apply(this, arguments);  
  26.         this.b = 2;  
  27.     },  
  28.       
  29.     getB : function(){  
  30.         return this.b;  
  31.     }  
  32. }).extend(A);  
  33.   
  34. var C = new Class({  
  35.     initialize: function(){  
  36.         C.parent.initialize.apply(this, arguments);  
  37.         this.c = 3;  
  38.     },  
  39.       
  40.     getC : function(){  
  41.         return this.c;  
  42.     },  
  43.       
  44.     getAll : function(){  
  45.         return this.getC() + ":" + this.getB() + ":" + this.getA();  
  46.     }  
  47.       
  48. }).extend(B);  
  49.   
  50. var c = new C;  
  51. alert(c.getA() + ":" + c.getB() + ":" + c.getC()); // 1:2:3  
  52. alert(c.getAll()); // 3:2:1  
az osztály változókat átírtam nagybetűssé...

üdv Csaba
2

Ez is egy lehetőség

inf · 2010. Jan. 2. (Szo), 15.03
Igen, ez is egy lehetőség, de úgy szeretném megoldani a dolgot, hogy az osztály nevek ne szerepeljenek. Mert amit írtál, ahelyett ennyi erővel ki is lehetne hatni ezt a parent-es dolgot:
  1.       
  2. Class=function (source)  
  3. {  
  4.     return function ()  
  5.     {  
  6.         if (this.initialize instanceof Function)  
  7.         {  
  8.             this.initialize.apply(this,arguments);  
  9.         }  
  10.     }.implement(source);  
  11. };  
  12.   
  13. Function.prototype.extend(  
  14. {  
  15.     extend: function (source)  
  16.     {  
  17.         this.prototype.extend(source.prototype);  
  18.         return this;  
  19.     },  
  20.     implement: function (source)  
  21.     {  
  22.         this.prototype.implement(source);  
  23.         return this;  
  24.     }  
  25. });  
  26.       
  27. var A=new Class(  
  28. {  
  29.     initialize: function ()  
  30.     {  
  31.         this.a=1;  
  32.     }  
  33. });  
  34.   
  35. var B=new Class(  
  36. {  
  37.     initialize: function ()  
  38.     {  
  39.         A.prototype.initialize.apply(this,arguments);  
  40.         this.b=1;  
  41.     }  
  42. }).extend(A);  
  43.   
  44. var C=new Class(  
  45. {  
  46.     initialize: function ()  
  47.     {  
  48.         B.prototype.initialize.apply(this,arguments);  
  49.         this.c=1;  
  50.     }  
  51. }).extend(B);  
Szóval a dolog lényege pont az, hogy az osztályok nevei ne szerepeljenek a függvényekben. Viszont a dolog lényege meg pont az, hogy a függvények-et hozzá kéne kötni valahogyan az osztályokhoz. Pl a szülő init-jét a szülőhöz stb.. Ezzel viszont az a probléma, hogy nem egyszerű :-) Pl azt nem lehet mondani, hogy arguments.callee.ownerClass, mert egy függvényt interface-ből is hozzáadhatok több osztályhoz, és azokból örököltethetem. Interface-ben mondjuk nem lehet parent-et hívni, hmm nemsokára előállok valamivel.

No az interface-el annyi a gond, hogy js-ben csak megvalósítást lehet megadni absztrakció helyett. Ettől függetlenül megoldottam úgy, hogy az alapból megadott függvényeket az osztályhoz társítja, az implementáltakat pedig nem.
  1. Object.prototype.each=function (method,context)  
  2. {  
  3.     if (!context)  
  4.     {  
  5.         context=this;  
  6.     }  
  7.     for (var property in this)  
  8.     {  
  9.         if  
  10.         (  
  11.             !(property in Object.prototype)  
  12.         ||  
  13.             this[property]!==Object.prototype[property]  
  14.         )  
  15.         {  
  16.             method.call(context,property,this[property]);  
  17.         }  
  18.     }  
  19.     return context;  
  20. };  
  21.   
  22. Object.prototype.implement=function (source)  
  23. {  
  24.     if (source)  
  25.     {  
  26.         source.each(function (property,value)  
  27.         {  
  28.             this[property]=source[property];  
  29.         },this);  
  30.     }  
  31.     return this;  
  32. };  
  33.   
  34. Object.prototype.extend=function (source)  
  35. {  
  36.     if (source)  
  37.     {  
  38.         source.each(function (property,value)  
  39.         {  
  40.             if (  
  41.                 !(property in this)  
  42.             ||  
  43.                 (  
  44.                     (property in Object.prototype)  
  45.                 &&  
  46.                     this[property]===Object.prototype[property]  
  47.                 )  
  48.             )  
  49.             {  
  50.                 this[property]=source[property];  
  51.             }  
  52.         },this);  
  53.     }  
  54.     return this;  
  55. };  
  56.   
  57. Function.prototype.each=function (method,context)  
  58. {  
  59.     if (!context)  
  60.     {  
  61.         context=this;  
  62.     }  
  63.     return this.prototype.each(method,context);  
  64. };  
  65.   
  66. Function.prototype.implement=function (source)  
  67. {  
  68.     this.prototype.implement(source);  
  69.     return this;  
  70. };  
  71.   
  72. Function.prototype.extend=function (source)  
  73. {  
  74.     if (!this.parent)  
  75.     {  
  76.         this.parent=source;  
  77.         this.prototype.extend(source.prototype);  
  78.         this.each(function (property,method)  
  79.         {  
  80.             if ((method instanceof Function) && method.Class==this)  
  81.             {  
  82.                 method.parent=source.prototype;  
  83.             }  
  84.         });  
  85.     }  
  86.     return this;  
  87. };  
  88.   
  89.   
  90. Class=function (source)  
  91. {  
  92.     return function ()  
  93.     {  
  94.         if (this.initialize instanceof Function)  
  95.         {  
  96.             this.initialize.apply(this,arguments);  
  97.         }  
  98.     }.implement(source).each(function (property,method)  
  99.     {  
  100.         if (method instanceof Function)  
  101.         {  
  102.             method.Class=this;  
  103.         }  
  104.     });  
  105. };  
  106.   
  107.   
  108. var a=new Class(  
  109. {  
  110.     initialize: function ()  
  111.     {  
  112.         this.a=1;  
  113.     }  
  114. });  
  115.   
  116. var b=new Class(  
  117. {  
  118.     initialize: function ()  
  119.     {  
  120.         arguments.callee.parent.initialize.apply(this,arguments);  
  121.         this.b=1;  
  122.     }  
  123. }).extend(a);  
  124.   
  125. var c=new Class(  
  126. {  
  127.     initialize: function ()  
  128.     {  
  129.         arguments.callee.parent.initialize.apply(this,arguments);  
  130.         this.c=1;  
  131.     }  
  132. }).extend(b);  
  133.   
  134. var d=new c;  
  135. alert(d.a && d.b && d.c);  
Persze lehetne valami this.getParent()-es dolog is arguments.callee.caller-el, de úgy emlékszem az nem cross-browser.
3

második blikk : klauzúra

toxin · 2010. Jan. 2. (Szo), 16.28
ha annyi módosítás belefér, hogy
  1. this.parent.initialize.apply(this,arguments);  
helyett
  1. this._parent_initialize(arguments);  
stb. akkor :
  1. bind = function(f,context){  
  2.     return function(){  
  3.         f.apply(context, arguments);  
  4.     }  
  5. }  
  6.               
  7. Object.prototype.extend = function(source){  
  8.     if (source) {  
  9.         for (var property in source)(bind(function(property){  
  10.             if ((property in Object.prototype) ? source[property] !== Object.prototype[property] &&  
  11.             this[property] === Object.prototype[property] : !(property in this)) {  
  12.                this[property] = source[property];               
  13.             }else if (!(/_parent_/.test(property)) && !(property in Object.prototype) && property in this){               
  14.                 var prop = property, target = null;  
  15.                 this["_parent_" + prop] = function(){  
  16.                     // we are in the instance !!!  
  17.                     target = !target ? source : target.parent;  
  18.                     var ret = target[prop].apply(this,arguments);  
  19.                     target = null;  
  20.                     return ret;                               
  21.                 }  
  22.             }   
  23.         },this))(property);  
  24.         return this;  
  25.     }                  
  26. };  
  27.   
  28. Object.prototype.implement = function(source){  
  29.     if (source) {  
  30.         for (var property in source) {  
  31.             if (!(property in Object.prototype) ||  
  32.             source[property] !== Object.prototype[property]) {  
  33.                 this[property] = source[property];  
  34.             }  
  35.         }  
  36.     }  
  37.     return this;  
  38. };  
  39.   
  40. Class = function(source){  
  41.     return function(){  
  42.         if (this.initialize instanceof Function) {  
  43.             this.initialize.apply(this, arguments);  
  44.         }  
  45.     }  
  46. .implement(source);  
  47. };  
  48.   
  49. Function.prototype.extend({  
  50.     extend: function(source){  
  51.         this.prototype.extend(source.prototype);  
  52.         this.prototype.parent = source.prototype;  
  53.         return this;  
  54.     },  
  55.     implement: function(source){  
  56.         this.prototype.implement(source);  
  57.         return this;  
  58.     }  
  59. });  
  60.   
  61. var A = new Class({  
  62.     initialize: function(){  
  63.         this.fooVar = 1;  
  64.         this.a = 1;  
  65.     },  
  66.       
  67.     get : function(){  
  68.         alert( this.fooVar );  
  69.     },  
  70.       
  71.     getA : function(){  
  72.         return this.a;  
  73.     }  
  74. });  
  75.   
  76. var B = new Class({  
  77.     initialize: function(){  
  78.         this._parent_initialize(arguments);  
  79.         this.fooVar = 2;  
  80.         this.b = 2;  
  81.     },  
  82.       
  83.     get : function(){  
  84.         this._parent_get();  
  85.         alert( this.fooVar );  
  86.     },  
  87.       
  88.     getB : function(){  
  89.         return this.b;  
  90.     }  
  91.       
  92. }).extend(A);  
  93.   
  94. var C = new Class({  
  95.     initialize: function(){  
  96.         this._parent_initialize(arguments);  
  97.         this.fooVar = 3;  
  98.         this.c = 3;  
  99.     },  
  100.       
  101. //  get : function(){} a szülő osztályból  
  102.       
  103.     getC : function(){  
  104.         return this.c;  
  105.     },  
  106.       
  107.     getAll : function(){  
  108.         alert( this.getC() + ":" + this.getB() + ":" + this.getA() );  
  109.     }  
  110.       
  111. }).extend(B);  
  112.   
  113. var c = new C;  
  114. c.get(); // 3 3 3  
  115. c.getAll(); // 3 : 2 : 1  
a lényegi rész az eleje, azután nincs lényeges módosítás
  1. bind = function(f,context){  
  2.     return function(){  
  3.         f.apply(context, arguments);  
  4.     }  
  5. }  
  6.               
  7. Object.prototype.extend = function(source){  
  8.     if (source) {  
  9.         for (var property in source)(bind(function(property){  
  10.             if ((property in Object.prototype) ? source[property] !== Object.prototype[property] &&  
  11.             this[property] === Object.prototype[property] : !(property in this)) {  
  12.                this[property] = source[property];               
  13.             }else if (!(/_parent_/.test(property)) && !(property in Object.prototype) && property in this){               
  14.                 var prop = property, target = null;  
  15.                 this["_parent_" + prop] = function(){  
  16.                     // we are in the instance !!!  
  17.                     target = !target ? source : target.parent;  
  18.                     var ret = target[prop].apply(this,arguments);  
  19.                     target = null;  
  20.                     return ret;                               
  21.                 }  
  22.             }   
  23.         },this))(property);  
  24.         return this;  
  25.     }                  
  26. };  
bind a for/klauzúra miatt kellett, elv : ha adott osztályban van már olyan metódus mint a szűlőben : _parent_ prefixel elérhetővé tettem, és közben klauzúra segítségével nyilvántartottam hogy melyik szinten vagyunk az öröklődési fában (amin megyünk felfele), ha vége az adott hívási láncnak : akkor vissza alaphelyzetbe + return ... nem mondom hogy hibátlan de gondolkodjon más is :) ill. egyszer már nekifutottam ennek lásd : http://weblabor.hu/forumok/temak/21044#comment-52091

üdv Csaba
4

Beleférne

inf · 2010. Jan. 2. (Szo), 16.30
Hasonlót már csináltam static-al, ott valami ilyesmi volt:
  1. var X=new Class(  
  2. {  
  3.     static_inspect: function ()  
  4.     {  
  5.         alert("Huhh!");  
  6.     }  
  7. });  
  8. X.inspect();//Huhh!  
A this.parent_initialize beleférne, viszont szerintem nem megoldható. A kód, amit írtál nagyon nincs rendben.

Ott kezdődik, hogy a Object.prototype.extend csak egy segédfüggvény, aminek semmi köze nincs az osztályokhoz. Annyit csinál, hogy hozzáadja a source tulajdonságait az objektumhoz, ha még nincsenek megadva.

pl:
  1. var o=({a:1}).extend({a:2,b:2});  
  2. alert(o.a+","+o.b); //1,2  
this-ből kiindulva a bind-hoz hasonló módon lehet megoldani, csak bonyolultabban.
A függvények köré olyan burkoló függvényt kell tenni, ami a this.parent értékét folyamatosan átírja. Meg lehet oldani ezen az úton is, de az már inkább gányolás kategória. A burkolófüggvényes megoldásokat nem szívesen használom amúgy sem, mert egy függvény hívásból kettőt csinálnak. (Mondjuk az apply vagy a call is, de azok legalább beépítettek...)
5

javítás

toxin · 2010. Jan. 2. (Szo), 17.41
  1. Object.prototype.extend = function(source){  
  2.     if (source) {  
  3.         var that = this;  
  4.         for (var property in source)(function(){  
  5.             if ((property in Object.prototype) ? source[property] !== Object.prototype[property] &&  
  6.             that[property] === Object.prototype[property] : !(property in that)) {  
  7.                that[property] = source[property];               
  8.             }else if (!(/_parent_/.test(property)) && !(property in Object.prototype) && property in that){               
  9.                   
  10.                 var prop = property, target = null;  
  11.                 that["_parent_" + prop] = function(){  
  12.                     // we are in the instance !!!  
  13.                     var prevTarget = target;  
  14.                     target = !target ? source : target.parent;  
  15.                     var ret = target[prop].apply(this,arguments);  
  16.                     target = prevTarget;  
  17.                     return ret;                               
  18.                 }  
  19.                   
  20.             }   
  21.         })();  
  22.         return that;  
  23.     }                  
  24. };  
bind-ot kiszedtem, és az osztályhierarchia nyilvántartást is finomítottam, előbbi verzióban gond lett volna, ha adott szintről egymás után többször is hívjuk az odatartozó _parent_ tagmetódust

üdv Csaba

ui: hogy most gány vagy nem, ha lett volna jobb ötletem azt írom be ;), jó rég foglalkoztam ilyesmivel komolyabban...sajnos nem tipikus napi feladat, "hogy a Object.prototype.extend csak egy segédfüggvény" ha már müxik oda rakod ahova akarod :) engem most csak a probléma izgatott (mint logikai feladat :) )
6

Tetszik

inf · 2010. Jan. 2. (Szo), 17.46
Ja, valami ilyenre gondoltam, amikor burkolófüggvényes megoldásról beszéltem. Az elve az szép, viszont többszörös öröklődésnél nem vagyok benne biztos, hogy jól hívja a függvényeket. Gondolok itt valami ilyesmire:
  1. var A=new Class(  
  2. {  
  3.     test: function ()  
  4.     {  
  5.         this.a=1;  
  6.     }  
  7. });  
  8.   
  9. var B=new Class(  
  10. {  
  11.     test: function ()  
  12.     {  
  13.         this.parent_test();  
  14.         this.a2=2;  
  15.     }  
  16. }).extend(A);  
  17.   
  18. var C=new Class(  
  19. {  
  20.     b: function ()  
  21.     {  
  22.         this.test();  
  23.     }  
  24. }).extend(B);  
  25.   
  26. var d=new C;  
  27. d.b();  
Ránézésre a te megoldásod ettől végtelen ciklusba kerülne, de nem próbáltam ki. :-) Majd holnap összehozok valami hasonlót, mint amit csináltál.
7

még bírja :)

toxin · 2010. Jan. 2. (Szo), 17.58
  1. Object.prototype.extend = function(source){  
  2.     if (source) {  
  3.         var that = this;  
  4.         for (var property in source)(function(){  
  5.             if ((property in Object.prototype) ? source[property] !== Object.prototype[property] &&  
  6.             that[property] === Object.prototype[property] : !(property in that)) {  
  7.                that[property] = source[property];               
  8.             }else if (!(/_parent_/.test(property)) && !(property in Object.prototype) && property in that){               
  9.                   
  10.                 var prop = property, target = null;  
  11.                 that["_parent_" + prop] = function(){  
  12.                     // we are in the instance !!!  
  13.                     var prevTarget = target;  
  14.                     target = !target ? source : target.parent;  
  15.                     var ret = target[prop].apply(this,arguments);  
  16.                     target = prevTarget;  
  17.                     return ret;                               
  18.                 }  
  19.                   
  20.             }   
  21.         })();  
  22.         return that;  
  23.     }                  
  24. };  
  25.   
  26. Object.prototype.implement = function(source){  
  27.     if (source) {  
  28.         for (var property in source) {  
  29.             if (!(property in Object.prototype) ||  
  30.             source[property] !== Object.prototype[property]) {  
  31.                 this[property] = source[property];  
  32.             }  
  33.         }  
  34.     }  
  35.     return this;  
  36. };  
  37.   
  38. Class = function(source){  
  39.     return function(){  
  40.         if (this.initialize instanceof Function) {  
  41.             this.initialize.apply(this, arguments);  
  42.         }  
  43.     }  
  44. .implement(source);  
  45. };  
  46.   
  47. Function.prototype.extend({  
  48.     extend: function(source){  
  49.         this.prototype.extend(source.prototype);  
  50.         this.prototype.parent = source.prototype;  
  51.         return this;  
  52.     },  
  53.     implement: function(source){  
  54.         this.prototype.implement(source);  
  55.         return this;  
  56.     }  
  57. });  
  58.   
  59. var A=new Class(  
  60. {  
  61.     test: function ()  
  62.     {  
  63.         console.log("3");  
  64.         this.a=1;  
  65.     }  
  66. });  
  67.   
  68. var B=new Class(  
  69. {   
  70.     test: function ()  
  71.     {  
  72.         console.log("2");  
  73.         this._parent_test();  
  74.         console.log("4");  
  75.         this.a2=2;  
  76.     }  
  77. }).extend(A);  
  78.   
  79. var C=new Class(  
  80. {  
  81.     b: function ()  
  82.     {  
  83.         console.log("1");  
  84.         this.test();  
  85.         console.log("5");  
  86.     }  
  87. }).extend(B);  
  88.   
  89. var d=new C;  
  90. d.b();  
konzolban: 1 2 3 4 5

üdv Csaba
8

azért nem tökéletes

inf · 2010. Jan. 2. (Szo), 19.21
  1. var A=new Class(    
  2. {    
  3.    test: function ()    
  4.    {    
  5.        alert("2");  
  6.    }    
  7. });    
  8.    
  9. var B=new Class(    
  10. {     
  11.    test: function ()    
  12.    {    
  13.        alert("1");    
  14.        this._parent_test();    
  15.        alert("3");   
  16.    }    
  17. }).extend(A);    
  18.    
  19. var C=new Class({}).extend(B);    
  20.   
  21. var D=new Class(  
  22. {  
  23.    test: function ()    
  24.    {    
  25.        alert("0");    
  26.        this._parent_test();    
  27.        alert("4");    
  28.    }  
  29. }).extend(C);  
  30.    
  31. var d=new D;    
  32. d.test();    
9

javitás

toxin · 2010. Jan. 3. (V), 13.43
kiraktam külön függvénybe a _parent_ -el kapcsolatos módosításkoat
  1. Object.prototype.extend = function(source){  
  2.     if (source) {  
  3.         for (var property in source) {  
  4.             if ((property in Object.prototype) ? source[property] !== Object.prototype[property] &&  
  5.             this[property] === Object.prototype[property] : !(property in this)) {  
  6.                 this[property] = source[property];  
  7.             }  
  8.         }  
  9.     }  
  10.     return this;  
  11. };  
  12.   
  13. Object.prototype.implement = function(source){  
  14.     if (source) {  
  15.         for (var property in source) {  
  16.             if (!(property in Object.prototype) ||  
  17.             source[property] !== Object.prototype[property]) {  
  18.                 this[property] = source[property];  
  19.             }  
  20.         }  
  21.     }  
  22.     return this;  
  23. };  
  24.   
  25. Class = function(source){  
  26.     return function(){  
  27.         if (this.initialize instanceof Function) {  
  28.             this.initialize.apply(this, arguments);  
  29.         }  
  30.     }  
  31. .implement(source);  
  32. };  
  33.   
  34. Function.prototype.extend({  
  35.     extend: function(source){  
  36.         this.prototype.extend(source.prototype);  
  37.         this.prototype.parent = source.prototype;  
  38.         patchInheritance(this.prototype, source.prototype);   
  39.         return this;  
  40.     },  
  41.     implement: function(source){  
  42.         this.prototype.implement(source);  
  43.         return this;  
  44.     }  
  45. });  
  46.   
  47. function patchInheritance(_class, _parentClass){  
  48.     for (var property in _parentClass)(function(){  
  49.         if (!(/_parent_/.test(property)) &&  
  50.             !(property in Object.prototype) &&   
  51.             property in _class  
  52.             ) {  
  53.             var prop = property, klass = null;  
  54.             _class["_parent_" + property] = function(){  
  55.                 var prevKlass = klass;  
  56.                 klass = !klass ? _parentClass : klass.parent;  
  57.                 var ret = klass[prop].apply(this, arguments);  
  58.                 klass = prevKlass;  
  59.                 return ret;  
  60.             }  
  61.         }  
  62.     })();                 
  63. }  
  64.   
  65. var A = new Class({  
  66.     test: function(){  
  67.         console.log(this.getClass() + ":" + "2");  
  68.     },  
  69.       
  70.     getClass : function(){  
  71.         return "A";  
  72.     }  
  73.                       
  74. });  
  75.   
  76. var B = new Class({  
  77.     test: function(){  
  78.         console.log(this.getClass() + ":" +"1");  
  79.         this._parent_test();  
  80.         console.log(this.getClass() + ":" +"3");  
  81.     },  
  82.       
  83.     getClass : function(){  
  84.         return "B";  
  85.     }  
  86.       
  87. }).extend(A);  
  88.   
  89. var C = new Class({               
  90.     getClass : function(){  
  91.         return "C";  
  92.     }                 
  93. }).extend(B);  
  94.   
  95. var D = new Class({  
  96.     test: function(){  
  97.         console.log(this.getClass() + ":" +"0");  
  98.         this._parent_test();  
  99.         console.log(this.getClass() + ":" +"4");  
  100.     },  
  101.       
  102.     getClass : function(){  
  103.         return "D";  
  104.     }             
  105.       
  106. }).extend(C);  
  107.   
  108. var d = new D;  
  109. d.test();  
konzolban :
D:0
D:1
D:1
D:2
D:3
D:3
D:4

kontextus nem változik, de lépked felfele az öröklődőséi fán, ha átírom a
  1. var ret = klass[prop].apply(this, arguments);   
  1. var ret = klass[prop].apply(klass, arguments);   
-ra, azaz ha a kontextust adott prototype objektumra állítom, a kimenet:
D:0
C:1
B:1
A:2
B:3
C:3
D:4

jónak látszik

üdv Csaba

jav. :

és ígymár a tegnapi
  1. var A=new Class(  
  2. {  
  3.     test: function ()  
  4.     {  
  5.         console.log("3");  
  6.         this.a=1;  
  7.     }  
  8. });  
  9.   
  10. var B=new Class(  
  11. {   
  12.     test: function ()  
  13.     {  
  14.         console.log("2");  
  15.         this._parent_test();  
  16.         console.log("4");  
  17.         this.a2=2;  
  18.     }  
  19. }).extend(A);  
  20.   
  21. var C=new Class(  
  22. {  
  23.     b: function ()  
  24.     {  
  25.         console.log("1");  
  26.         this.test();  
  27.         console.log("5");  
  28.     }  
  29. }).extend(B);  
  30.   
  31. var d=new C;  
  32. d.b();  
is a helyes :
1
2
2
3
4
4
5

kimenetet adja, 1 2 3 4 5 helyett, ooopsi
10

:D

inf · 2010. Jan. 3. (V), 19.38
Egy kis plusz logikát kéne belevinni, hogy bizonyos esetekben máshogy viselkedjen... (Ne csak egyet lépjen felfele a fán etc...)
11

Saját

inf · 2010. Jan. 6. (Sze), 13.12
Csináltam én is burkolófüggvényeset az én megközelítésemmel.
  1. Object.prototype.each=function(method,context)  
  2. {  
  3.     if (!context)  
  4.     {  
  5.         context=this;  
  6.     }  
  7.     for (var property in this)  
  8.     {  
  9.         var value=this[property];  
  10.         if (  
  11.             !(property in Object.prototype)  
  12.         ||  
  13.             value!==Object.prototype[property]  
  14.         )  
  15.         {  
  16.             method.call(context,property,value);  
  17.         }  
  18.     }  
  19.     return context;  
  20. };  
  21.   
  22. Object.prototype.extend=function(source)  
  23. {  
  24.     if (source)  
  25.     {  
  26.         for (var property in source)  
  27.         {  
  28.             if (  
  29.                 (property in Object.prototype)  
  30.                 ?  
  31.                     (  
  32.                         source[property]!==Object.prototype[property]  
  33.                     &&  
  34.                         this[property]===Object.prototype[property]  
  35.                     )  
  36.                 :  
  37.                     (  
  38.                         !(property in this)  
  39.                     )  
  40.             )  
  41.             {  
  42.                 this[property]=source[property];  
  43.             }  
  44.         }  
  45.     }  
  46.     return this;  
  47. };  
  48.   
  49. Object.prototype.implement=function(source)  
  50. {  
  51.     if (source)  
  52.     {  
  53.         for (var property in source)  
  54.         {  
  55.             if (  
  56.                 !(property in Object.prototype)  
  57.             ||  
  58.                 source[property]!==Object.prototype[property]  
  59.             )  
  60.             {  
  61.                 this[property]=source[property];  
  62.             }  
  63.         }  
  64.     }  
  65.     return this;  
  66. };  
  67.   
  68. Class=function(source)  
  69. {  
  70.     return function()  
  71.     {  
  72.         if (this.initialize instanceof Function)  
  73.         {  
  74.             this.initialize.apply(this,arguments);  
  75.         }  
  76.     }.implement(source);  
  77. };  
  78.   
  79. Function.prototype.extend(  
  80. {  
  81.     extend: function(parent)  
  82.     {  
  83.         if (this.parent)  
  84.         {  
  85.             return this;  
  86.         }  
  87.         this.parent=parent;  
  88.         this.prototype.extend(parent.prototype);  
  89.         return this;  
  90.     },  
  91.     implement: function(source)  
  92.     {  
  93.           
  94.         var Class=this;  
  95.         return source.each(function (property,value)  
  96.         {  
  97.             this.prototype[property]=(value instanceof Function)  
  98.                 ?function ()  
  99.                 {  
  100.                     var parent=this.parent;  
  101.                     this.parent=Class.parent && Class.parent.prototype;  
  102.                     var result=value.apply(this,arguments);  
  103.                     this.parent=parent;  
  104.                     return result;  
  105.                 }  
  106.                 :value;  
  107.         },this);  
  108.     }  
  109. });  
  110.   
  111. var A=new Class(  
  112. {  
  113.     initialize: function ()  
  114.     {  
  115.         alert("0");  
  116.     }  
  117. });  
  118.   
  119. var B=new Class(  
  120. {  
  121.     initialize: function ()  
  122.     {  
  123.         this.parent.initialize.apply(this,arguments);  
  124.         alert("1");  
  125.     }  
  126. }).extend(A);  
  127.   
  128. var C=new Class(  
  129. {  
  130.     initialize: function ()  
  131.     {  
  132.         this.parent.initialize.apply(this,arguments);  
  133.         alert("2");  
  134.     }  
  135. }).extend(B);  
  136.   
  137. var D=new Class(  
  138. {  
  139.     initialize: function ()  
  140.     {  
  141.         this.parent.initialize.apply(this,arguments);  
  142.         alert("3");  
  143.     }  
  144. }).extend(C);  
  145.   
  146. new D;