-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Why aren't methods merged by extending the instance's prototype chain? #313
Comments
hi there! Gonna list the reasons. Some might not be hard reasons, but combined they are a solid answer.
I can't imagine how a prototype chain can help me with that. I hope I answered your question right. If not, feel free to ask. |
Hi @koresar, thank you for that answer. If I might just respond to each point in turn:
Agreed, but this is the very point I was responding to. :)
There could either be an object in the chain that contains no own properties or one could optimise that object out and directly link child prototype to parent.
Yet the incumbent merge operation effectively linearises such compositions already. It's no different.
I thought the driving issue was to provide multiple inheritance, though I readily admit I need to watch Eric's talk again. I'm not convinced a chain of 10 prototypes is any more difficult to reason about than a composition of 10 stamps?
This is a fair point, and one could certainly give developers the choice of inheritance methodology so that merge can be preferred over prototype chaining where performance is an issue.
Thanks, will do.
As above, the incumbent merge operation is effectively linearising your composition already. |
Thanks for the reply. I eager to see your linearisation algorithm. 👍 |
@koresar: Surely it depends on the order of your existing composition? |
@eggyal the tree is the order. For example,
Hopefully, I'm clear enough. |
But I mean, how are siblings currently composed? Isn't |
@eggyal here is the reference implementation with comments: https://github.com/stampit-org/stamp-specification/blob/master/compose.js#L189 And here is the corresponding phrase from the specification:
|
It is called class-factory mixins, as alternative to concatenation. |
ES6 let's you do class Foo {...}
class Bar {...}
class Baz extends Bar {...}
class Blah {...}
class Lorem extends multiple(Foo, Baz, Blah) {...}
// or, depending on the prototype chain ordering that you want
class Lorem extends multiple(Baz, Foo, Blah) {...}
function multiple () {
// ... I leave you to imagine the implementation ...
} This is what Stampit seems to be purposed for, but it can also be done with ES6 classes and prototype chaining rather than with concatenation. |
Here's an example of multiple inheritance with class factory mixins in practice: https://github.com/trusktr/infamous/blob/master/src/motor/Sizeable.js#L26 ES6 classes are not limited by arthritic problems cause by single inheritance. |
As bonus, here's two
The non-failing solution can be made with I don't really see a good enough reason to use Stampit when I can achieve the same with ES6 classes. Am I missing anything? |
Also note in my above linked example of the Sizeable class, the mixins can be used as classes. F.e. , it could be class Sizeable extends TreeNode {}
// or
class Sizeable extends TreeNode.mixin(Observable) {}
// or
class Sizeable extends TreeNode.mixin(Observable.mixin(AnyOtherClass)) {}
// and, in the last case
const s = new Sizeable
s instanceof TreeNode // true
s instanceof Observable // true
s instanceof AnyOtherClass // true |
In my opinion, stamps are more about the ecosystem. You have some standardized descriptor that can be used to create stamp even without any supporting library since it's just POJO. Our monorepo is still at the beginning, but eventually, there could be many useful stamps that can be just composed together. On the contrary, your solution with |
If you mean that the In the very near future, it will be as simple as import multiple from 'http://some-cdn.com/path/to/multiple/vXXX' Stampit is also library support. Object.assign is also built-in library support. Having to import something or even copy/paste it is not really a huge problem! |
I did not really try to imply it's a problem, but doesn't that mean you will be creating another kind of ecosystem similar to stamps? What is the benefit then? If classes would support multiple inheritances out of box then hell yea, it would be awesome, but they don't... Also, it seems to me that classes can be rather limited in many ways and often you have to end up with various hacks (I personally consider Proxy a hack kinda). For example look at our privatize stamp. You cannot really do something that easy with classes if I am not mistaken. And I am not sure about inheriting static properties/methods on classes. I did not dive into your solution, but can you like mixin together classes along with its statics? There is of course question of the need and if it's antipattern or not, but with stamps it definitely feels more natural and wanted. |
Hi @trusktr Thank you very much for that deep insight into the awesome ES usage. You reminded me that there are already a bunch of ways to solve the "class inheritance" problem.
There is no clear winner. Every approach has pros and cons. Since I'm using stamps a lot I'm going to list Pros of the stampit project:
A plan for the future: create the Have a great coding, everyone. It's great to see so many ideas about object composition! The more we try - the more we learns as a community. 👍 |
I disabled On that note, ES6 introduced a way to override broken
Currently, switching from constructors to factories is a breaking change, and there are many reasons you might want to do so, including the need for dynamic abstract factories, object pools, proxies, etc... The change is so common, it's included a refactoring catalog in the book, "Refactoring" by Martin Fowler, Kent Beck, John Brant, William Opdyke, and Don Roberts. That refactoring is not safe to do in JavaScript if you allow callers to use As long as those problems exist, stamps should not enable |
Closing as "by design" and "now an issue" kind of :) |
This is less an issue and more a question/discussion over the design/specification. Apologies if this is not the right forum.
In #257 (comment), @koresar says:
Why is this? I see that the prototype of stamped objects is their descriptor's
methods
, which is great—but why does not the merging of new methods, e.g. when composing stamps, not simply extend that prototype chain rather than merely create a new base prototype? That is:It seems to me that prototype chaining is far more powerful, expressive and useful. Why was the design decision taken not to use it?
The text was updated successfully, but these errors were encountered: