peterS.: Vererbung durch Delegation über Interfaces

Beitrag lesen

gruss PoWl, hallo molily, hallo Struppi;

Was ist ImageConstructor() eigentlich? Ist das nun eine normale
Funktion oder ein Objekt?

aus dem bauch heraus haette ich gesagt, dass es sich um einen
»Wrapper« (»Hüllenklasse« bzw. »Adapter«) handelt, moeglicherweise
hat aber allein Struppi mit dem »Decorator« recht.

Wozu ist dann allerdings das Schlüsselwort new nötig?

das ist, wie schon angemerkt, in der tat zuviel des guten.

anhand Deiner fragestellung laesst sich beispielhaft sehr gut die
anwendung von interfaces in JavaScript zeigen. dabei wird eine
funktion eben nicht als konstruktor zur instanziierung herangezogen.
ein schon existierendes objekt kann sich aber dieser funktion
bedienen, um dort auf oeffentlich (ueber [this]) vereinbarte
eigenschaften bzw. noch viel mehr auf solche methoden zuzugreifen,
um diese in seinem kontext auszufuehren.

code:

var EnhancedImage = (function () { // not to be used as constructor but as kind of interface  
  
  
 this.getSource = (function() {  
  
  return this.src;  
  });  
 this.setSource = (function(str) {  
  
  this.src = String(string);  
  });  
 this.getBorderWidth = (function() {  
  
  return this.border;  
  });  
 this.setBorderWidth = (function(num) {  
  
  this.border = Number(num);  
  });  
});  
  
  
var myImg = document.images[0];  
  
  
EnhancedImage.call(myImg); // [[EnhancedImage]] als interface auf [myImg] anwenden.  
  
  
alert("myImg.getSource() : " + myImg.getSource()); // http://src.selfhtml.org/logo.gif  
  
myImg.setBorderWidth(3);  
  
alert("myImg.getBorderWidth() : " + myImg.getBorderWidth()); // 3  
  
  
/*  
 naechste zeile bei geoeffneten SELFHTML Forum mal auf die locationbar des browsers loslassen:  
  
 javascript:var EnhancedImage = (function () {this.getSource = (function() {return this.src;});this.setSource = (function(str) {this.src = String(string);});this.getBorderWidth = (function() {return this.border;});this.setBorderWidth = (function(num) {this.border = Number(num);});});var myImg = document.images[0];EnhancedImage.call(myImg);alert("myImg.getSource() : " + myImg.getSource());myImg.setBorderWidth(3);alert("myImg.getBorderWidth() : " + myImg.getBorderWidth());  
*/

verfolgt man die idee nun weiter, um diese art der delegation noch komfortabler
ueber eigene methoden abzubilden, kommt man sicher auf aehnliche loesungen, wie
die beiden folgenden:

Function.prototype.implementedBy = (function (/*obj:Object|Function[, obj:Object|Function[, ...]]*/) {  
  
  
 var fct = this;  
  
 [link:http://forum.de.selfhtml.org/archiv/2007/3/t148291/@title=Array.forEach](arguments, (function (obj/*, idx, list*/) {  
  
  if (obj && ((typeof obj == "object") || (typeof obj == "function"))) {  
  
   fct.call(obj);  
  }  
 }));  
});  
  
  
Object.prototype.implements = (function(/*interface:Function[, interface:Function[, ...]]*/) {  
  
  
 var obj = this;  
  
 [link:http://www.pseliger.de/jsExtendedApi/jsApi.Array.mozGenerics.dev.js@title=Array.forEach](arguments, (function (fct/*, idx, list*/) {  
  
  if (typeof fct == "function") {  
  
  //fct.implementedBy(obj);  
   fct.call(obj);  
  }  
 }));  
});

das oben angefuehrte beispiel laesst sich in diesem fall nur mit
[function].implementedBy([object]) umsetzen, da [HTMLImageElement]e
als host-objekte bzw. objekte des DOM nicht in allen browsern
nativ prototypisch implementiert wurden.

[object].implements([function]) funktioniert wie gerade angedeutet
nur mit nativen JavaScript-objekten (also mit allen kern-objekten und
mit allen darauf basierenden selbstgetrickten objekten).

proof of concept:

Function.prototype.implementedBy = (function (/*obj:Object|Function[, obj:Object|Function[, ...]]*/) {  
  
  
 var fct = this;  
  
 Array.forEach(arguments, (function (obj/*, idx, list*/) {  
  
  if (obj && ((typeof obj == "object") || (typeof obj == "function"))) {  
  
   fct.call(obj);  
  }  
 }));  
});  
  
  
var EnhancedImage = (function () {  
  
  
 this.getSource = (function() {  
  
  return this.src;  
  });  
 this.setSource = (function(str) {  
  
  this.src = String(string);  
  });  
 this.getBorderWidth = (function() {  
  
  return this.border;  
  });  
 this.setBorderWidth = (function(num) {  
  
  this.border = Number(num);  
  });  
});  
  
  
var myImg = document.images[0];  
  
  
//EnhancedImage.call(myImg); // [[EnhancedImage]] als interface auf [myImg] anwenden.  
  
EnhancedImage.implementedBy(myImg); // [[EnhancedImage]] als interface auf [myImg] anwenden.  
  
  
alert("myImg.getSource() : " + myImg.getSource()); // http://src.selfhtml.org/logo.gif  
  
myImg.setBorderWidth(3);  
  
alert("myImg.getBorderWidth() : " + myImg.getBorderWidth()); // 3  
  
  
/*  
 naechste zeile bei geoeffneten SELFHTML Forum mal auf die locationbar eines gecko-browsers loslassen:  
  
 javascript:Function.prototype.implementedBy = (function () {var fct = this;Array.forEach(arguments, (function (obj) {if (obj && ((typeof obj == "object") || (typeof obj == "function"))) {fct.call(obj);}}));});var EnhancedImage = (function () {this.getSource = (function() {return this.src;});this.setSource = (function(str) {this.src = String(string);});this.getBorderWidth = (function() {return this.border;});this.setBorderWidth = (function(num) {this.border = Number(num);});});var myImg = document.images[0];EnhancedImage.implementedBy(myImg);alert("myImg.getSource() : " + myImg.getSource());myImg.setBorderWidth(3);alert("myImg.getBorderWidth() : " + myImg.getBorderWidth());  
*/

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:]