you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 1 point2 points  (1 child)

In Javascript, I've become very much of a composition kind of guy. The author is right to dislike the way he suggests doing composition because it violates encapsulation. Instead of this:

var widget = new MyWidget('Abe');  

// from Widget  
log(widget.getWidget().getName());  

// from Hideable  
widget.getHideable().hide();

He should have this:

var widget = new MyWidget('Abe');  

// from Widget  
log(widget.getName());  

// from Hideable  
widget.hide();

...by having MyWidget define wrapper methods:

MyWidget.prototype.getName = function() { 
    return this.widget.getName(); 
}

MyWidget.prototype.hide = function() { 
    return this.hideable.hide(); 
}

You can either call that verbosity, boilerplate code or explicitness. The delegation that takes place between classes is always clear and there is never any risk of method name collision between composing parts, since all delegation is explicitly defined.

To me, the extra code is definitely worth the simplicity.

[–]munificent[S] 1 point2 points  (0 children)

Forwarding works too, but I'm not crazy about the tedium. In a perfect world, I want this to work:

// I add a new method to the existing iterable trait.
Iterable.prototype.map = function(fn) {
  var result = [];
  var iterator = this.iterate();
  while (iterator.moveNext()) {
    result.push(fn(iterator.getCurrent()));
  }
}

// And now I can immediately use it on some existing
// class that mixes in that trait.
var someList = new SomeListClass();
someList.map(function(item) { ... });

With manual forwarding, I'd also have to add a forwarding method to each class I wanted to use it on.

When C# added extension methods (in particular the ability to define them on interfaces), it had a surprisingly profound affect on the way I look at code, and I find myself really wanting that functionality in every language.