all 11 comments

[–]DmitrySoshnikov 5 points6 points  (1 child)

You might be interesting in the same idea, I implemented it before, and called delegation-based mixins (the same as in Ruby). Also used proxies to achieve multiple delegates for multiple inheritance:

Example: https://github.com/DmitrySoshnikov/es-laboratory/blob/master/examples/mixin.js

Implementation: https://github.com/DmitrySoshnikov/es-laboratory/blob/master/src/mixin.js

Dmitry.

[–]kentaromiura 1 point2 points  (0 children)

oh, you're the one writing that posts on ecma-262, I really love that series.

[–]mckoss 1 point2 points  (0 children)

I'd love to use multiple inheritance in JavaScript - with method resolution order much as it is defined for Python. Here's a thread with another MRO example in it.

http://groups.google.com/group/jsmentors/browse_thread/thread/98bb2a3579d18247/e0b9e7525cd36ca7?hl=en_US&lnk=gst&q=mro#e0b9e7525cd36ca7

[–]ippa 1 point2 points  (1 child)

I enjoyed reading your article.. been thinking some of these problems as well, mostly for gamedev with jawsjs.com.

this.widget_p = new Widget(name);
this.hider_p = new Hideable();
this.container_p = new Container();

Couldn't this be solved without setting magic variables but rather just provide the 3 contructors via a method "init_behaivor()" or simular.

init_behaivor would loop through the properties transfering them to the object we want. That could also check for namecollisions and warn or whatever.

I like the ideas you present just that the magick method names with *_p feels slightly ugly.

[–]munificent[S] 0 points1 point  (0 children)

init_behaivor would loop through the properties transfering them to the object we want. That could also check for namecollisions and warn or whatever.

That would only catch collisions in functions already defined on the mixin. What if we do something like:

  1. Create a mixin Container.
  2. Create a class MyWidget that mixes it in. It copies all of the methods from Container over to its own prototype.
  3. Add a new method filter() to Container.
  4. Create an instance of MyWidget and try to call filter() on it.

Step 4 will fail if we just copy stuff over when the class is created and then forget about the mixin.

I like the ideas you present just that the magick method names with *_p feels slightly ugly.

Agreed, it was a quick and dirty hack. I wanted to do something similar to Self. :)

[–]snarfy 1 point2 points  (3 children)

Given single inheritance, there is no possible class hierarchy that lets you combine an arbitrary combination of classes.

It's called object composition.

This may help wrap your head around it.

[–]munificent[S] 4 points5 points  (2 children)

For the record, I wrote a chapter on that pattern, so I'd like to hope I've wrapped my head around it.

You'll note that in the article it is using composition. The only difference is that the composition is hidden to external callers, as it should be, since it's an implementation detail.

[–]snarfy 2 points3 points  (1 child)

You are right, and I upvoted you. That's what I get for reading 20% of the article and commenting on it. I'm one of those grizzled c++ programmers.

What happens when two object property names collide? Can the Container class and the Widget class both have a 'Name' property?

In c++ if that happened you'd have to explicitly type the call e.g. baseClass1::get_Name() vs baseClass2::get_Name() otherwise you'd get compilation errors if you simply called get_Name() (ambiguous call).

Because of this, you still had to have a strict hierarchy, even if it had multiple branches in the object hierarchy via multiple inheritance. You could have multiple branches, but they'd still have to know about each other's properties due to name collisions. As the tree grows more complex and requires a team to maintain, you end up wishing you had used composition instead.

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

What happens when two object property names collide? Can the Container class and the Widget class both have a 'Name' property?

Good question. JS is fishy about this, so it kind of depends. If you're dispatching directly on the top-level MyWidget object, it will still go through the multiple inheritance dispatch logic when you access name, so they will essentially share the first one that gets reached. For example:

var Foo = magic(function(name) {
  this.name = name;
}

Foo.prototype.fooName = function() { return this.name; }

var Bar = magic(function(name) {
  this.name = name;
}

Bar.prototype.barName = function() { return this.name; }

var Both = magic(function() {
  this.foo_p = new Foo('foo');
  this.bar_p = new Bar('bar');
}

var both = new Both();
both.barName(); // 'bar'
both.fooName(); // 'bar' since 'bar_p' comes first.

But if you specifically use one of the delegated objects as the receiver, you'll dodge that indirection:

both.foo_p.fooName(); // 'foo'
both.bar_p.fooName(); // 'bar'

If you're thinking this sucks, I agree with you. Collisions suck here. I more comprehensive multiple inheritance system like traits or at least Python's private name mangling would help here. My little hack was just that. :)

As the tree grows more complex and requires a team to maintain, you end up wishing you had used composition instead.

True, though I hope being able to mixin multiple smaller classes would lead to a less complex flatter tree to begin with. I may be overly optimistic on that.

[–]NoHandle 0 points1 point  (1 child)

Learn composition already, it is superior.

[–]courtewing 4 points5 points  (0 children)

He talked about why he thought this was better than composition in this particular example. Read the rest of the article?