peterS.: Mixin: Verhalten durch Delegation über implementierte Interfaces

hallo Interessierte,

was mich in letzter zeit immer mal wieder umtrieb, wie z.b. ...

... zur einfuehrung in/auf ...
  - »(JAVASCRIPT) vererbung / delegationsprinzipien« vom 14. 12. 2007,
  - »(JAVASCRIPT) Vererbung vs. Komposition - Delegation als Mittel der Wahl in JS« vom 13. 06. 2008,
  - »(JAVASCRIPT) beispielhafte Zusammenfassung von JavaScript als Sprache der OO.« vom 17. 06. 2008,
  - »(JAVASCRIPT) Multiparadigmensprachen, Klassifizierung von Sprachen der OOP« vom 13. 06. 2008,

... kurz und knackig formuliert und beispielhaft aufgezeigt in/auf (da war ich am naechsten dran) ...
  - »(JAVASCRIPT) Vererbung durch Delegation über Interfaces« vom 23. 07. 2008,

... umfangreicheres zeug in/auf (da trieb mich das *namensfindungsproblem* um) ...
  - »(JAVASCRIPT) Quadratur des Kreises lösen? DOM- und Sprachkern-Api versöhnen?« vom 19. 08. 2008,
  - »(JAVASCRIPT) weiteres beispiel zum besseren verstaendnis einer namensfindung« vom 20. 08. 2008,

... hat einen mich zufriedenstellenden abschluss gefunden.

die anwendung des immer wieder bemuehten delegationskonzepts steht
dem »Mixin« aus funktionalen und objektorientierten LISP-Dialekten
oder dem klassenbasierten Ruby am naechsten.

in den zuletzt von mir abgesetzten postings habe ich aus der not
der unsicherheit heraus diese konkrete anwendung in anlehnung an
den begriff »Constructor« dann auch ausschliesslich als »Functor«
bezeichnet.

richtig gluecklich war ich damit aber nicht. nicht zuletzt deshalb,
weil in JavaScript aus sicht der funktionalen programmierung fast
jede funktion/methode, die als argument einer anderen methode zum
zwecke des »Rückruf«s mitgegeben wird, das label »Funktor«
verdient. und »callback« bildet dieser spezielle fall gerade eben
nicht ab.

beim recherchieren zog sich der begriff »Delegation« zum glueck
wie ein roter faden durch alle gesichteten texte und im zusammenhang
mit »Mixin« stiess ich dann auch wieder auf solide erklaerungen
und beispiele, die dann doch das von mir von anfang an intuitiv
benutzte »Interface« benennen.

zusammenfassend lehne ich ich mich weit heraus und wage zu formulieren:

»Das "Mixin"-Konzept aus JavaScript-Sicht fügt Objekten Verhalten
 durch Delegation über implementierte Interfaces hinzu.«

die schon einmal in aehnlicher form beispielhaft angefuehrte
implementierung einer interface-methode [implementedBy] ...

Function.prototype.extend = (function (/*object:Object|Function[, object:Object|Function[, ...]]*/) { // *wording* korrigiert  
  
  
  var obj, fct = this;  
  
  for (var idx=0, len=arguments.length; idx<len; ++idx) {  
  
    obj = arguments[idx];  
    if (obj && ((typeof obj == "object") || (typeof obj == "function"))) {  
  
      fct.call(obj);  
    }  
  }  
});

... liesse sich sogar als *proof of concept* fuer eine [[Mixin]]-/
[Interface]-abstraktion selbst schreiben:

(function () { // code in die [[link:http://jconsole.com/]] rueberkopieren und ausfuehren.  
  
  
  var sh = (window || this);  
  
  
  sh.Mixin = (function () { // [http://en.wikipedia.org/wiki/Mixin]  
  
  
    this.extend = (function (/*object:Object|Function[, object:Object|Function[, ...]]*/) {  
  
      var obj, fct = this;  
      for (var idx=0, len=arguments.length; idx<len; ++idx) {  
  
        obj = arguments[idx];  
        if (obj && ((typeof obj == "object") || (typeof obj == "function"))) {  
  
          fct.call(obj);  
        }  
      }  
    });  
  });  
  
  
  Mixin.call(Function.prototype); // dies ist NICHT die prototypische erweiterung von [[Function]] in einer anderen schreibweise.  
  
  
  
  Object.prototype.extendBy = (function (/*interface:Function[, interface:Function[, ...]]*/) {  
  
  
    var fct, obj = this;  
    for (var idx=0, len=arguments.length; idx<len; ++idx) {  
  
      fct = arguments[idx];  
      if (typeof fct == "function") {  
  
        fct.call(obj);  
      }  
    }  
  });  
  
  
  delete sh;  
  delete arguments.callee;  
  
})();  
  
  
  
var SayHalloInterface = (function () {  
  
  this.sayHallo = (function () {  
  
    alert(this.hallo);  
  });  
});  
  
var hallo = {  
  
  hallo: "hallo ..."  
};  
var howdy = {  
  
  hallo: "howdy ..."  
};/*  
  
SayHalloInterface.call(hallo);  
SayHalloInterface.call(howdy);*/  
  
alert(SayHalloInterface.extend);  
  
SayHalloInterface.extend(hallo, howdy);  
  
hallo.sayHallo();  
howdy.sayHallo();  
  
  
  
var SayGoodByeInterface = (function () {  
  
  this.sayGoodBye = (function () {  
  
    alert(this.goodBye);  
  });  
});  
var SendMessageInterface = (function () {  
  
  this.sendMessage = (function () {  
  
    alert(this.msg);  
  });  
});  
  
hallo.goodBye = "... have to bid farewell";  
howdy.goodBye = "... bye";  
  
hallo.msg = "i'm fine";  
howdy.msg = "me's doing well";  
  
hallo.extendBy(SayGoodByeInterface, SendMessageInterface);  
howdy.extendBy(SayGoodByeInterface, SendMessageInterface);  
  
hallo.sayGoodBye();  
howdy.sayGoodBye();  
  
hallo.sendMessage();  
howdy.sendMessage();

weitere links:

danke fuer Eure aufmerksamkeit. rueckmeldungen sind wie immer willkommen.

so long - peterS. - pseliger@gmx.net

--
»Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]