r-proto-class
And even more sugared version - w/ class(...) wrapper over Object.create in this case gist.github.com/1367025, t.co/JnTnmd8c
You fell for the broken super implementation trapjsfiddle.net/Wtx3E/1
Your calling super methods with a value of this
that has references to
methods you don't expect it to have. i.e. if any sub class shadows a method
of a super class, then every reference to method invocation in the super
class will invoke the method of the sub class rather then the method of the
class itself.
super is not a beast you can implement trivially in ES. I actually have a stackoverflow questionstackoverflow.com/questions/8032566/emulate-super-in-javascriptabout
super.
You can't actually implement super without hard coupling a reference between Parent and Child. inheriting a generic super method from a prototype won't work as far as I know.
On 15.11.2011 17:34, Jake Verbaten wrote:
You fell for the broken super implementation trap jsfiddle.net/Wtx3E/1
Your calling super methods with a value of
this
that has references to methods you don't expect it to have. i.e. if any sub class shadows a method of a super class, then every reference to method invocation in the super class will invoke the method of the sub class rather then the method of the class itself.
I know perfectly this case. And yes, w/o caring additional info in the
context, that a method is called as a result of super', you can't determine correct value of
this' -- regardless whether you hardcode
names of classes or not.
OTOH, hypothetically, I can even imagine of of the solutions (though, of course again it's not for production, but as an experiment) -- to wrap every method with prologue that checks: if currently we are in a super-call, then get the prototype to which the method belongs (depending on the info from the super call):
this.move is transformed into:
if (this.currentlyInSuper) ... // take from parent proto else return this.move(...) // take original
super is not a beast you can implement trivially in ES. I actually have a stackoverflow question stackoverflow.com/questions/8032566/emulate-super-in-javascript about super.
Thanks, I also answer JS-questions (for the case) ;)
You can't actually implement super without hard coupling a reference between Parent and Child. inheriting a generic super method from a prototype won't work as far as I know.
Yep, it's hard, but seems possible (taking into account the idea described above).
Anyway, once again, the main point I wanted to note, is that we already may have more-less good classes via libs with more-less acceptable convenient super-calls. The standardized version should be better that all the libs. I.e.: (1) not to have the issue you describe and (2) which IMO even more important -- to be really a sugar, but not syntactically odd stuff.
Dmitry.
AFAIKT, your way of super-calling won’t work:
- When starting at the instance you skip the instance’s prototype.
- During each recursive call, you advance one object in the prototype chain. That won’t work if a super-method is not in the next object (that is, if there are holes in the chain).
Even with adding properties to objects (which is a no-no for ES.next), dynamic super is never particularly elegant. This was the best solution I could come up with and it’s not pretty: gist.github.com/1331748
Anyway, once again, the main point I wanted to note, is that we already may have more-less good classes via libs with more-less acceptable convenient super-calls. The standardized version should be better that all the libs. I.e.: (1) not to have the issue you describe and (2) which IMO even more important -- to be really a sugar, but not syntactically odd stuff.
Correct, we can implement these patterns, we just need a standardization mechanism, so that we no longer have hundreds of versions of this pattern.
I too believe that class is only sugar, however we do want to add new syntax to object literals.
Even with adding properties to objects (which is a no-no for ES.next), dynamic super is never particularly elegant. This was the best solution I could come up with and it’s not pretty: gist.github.com/1331748
If we could get away with manipulating the prototype chain at run time then super can be implemented as gist.github.com/1367167
The idea of temporarily plucking the current [[Prototype]] out of the chain, is how I envision super should work.
On 15.11.2011 18:13, Jake Verbaten wrote:
Even with adding properties to objects (which is a no-no for ES.next), dynamic super is never particularly elegant. This was the best solution I could come up with and it’s not pretty: https://gist.github.com/1331748
Is it based on the technique I showed before? Nice :) Though, where is the reference on the author, you cheat? :D
If we could get away with manipulating the prototype chain at run time then super can be implemented as gist.github.com/1367167
The idea of temporarily plucking the current [[Prototype]] out of the chain, is how I envision super should work.
Yeah-yeah, again -- we all agree that we already have nice class-sugar for 98% percents of case in the production programming. If the standard will ever standardize it, I'd like to see the sugar, but not the syntactically odd stuff. So, besides solving the 1-2% issues, the syntax we need (hello, Coffee).
Dmitry.
Even with adding properties to objects (which is a no-no for ES.next), dynamic super is never particularly elegant. This was the best solution I could come up with and it’s not pretty: gist.github.com/1331748
Is it based on the technique I showed before? Nice :) Though, where is the reference on the author, you cheat? :D
It’s very loosely based on Ashkenas’ approach, but there is a crucial difference: I don’t advance just one object for each recursive call, I traverse the prototype chain (for however long it takes) to find the next method and record it as here
(the object containing the method making a super-reference). Hence, my solution can handle “holes” in the prototype chain, Ashkenas’ solution can’t.
But I would not want to use that solution, a static approach is much more elegant.
On 15.11.2011 17:49, Dmitry Soshnikov wrote:
On 15.11.2011 17:34, Jake Verbaten wrote:
You fell for the broken super implementation trap jsfiddle.net/Wtx3E/1
Your calling super methods with a value of
this
that has references to methods you don't expect it to have. i.e. if any sub class shadows a method of a super class, then every reference to method invocation in the super class will invoke the method of the sub class rather then the method of the class itself.I know perfectly this case. And yes, w/o caring additional info in the context, that a method is called as a result of
super', you can't determine correct value of
this' -- regardless whether you hardcode names of classes or not.OTOH, hypothetically, I can even imagine of of the solutions (though, of course again it's not for production, but as an experiment) -- to wrap every method with prologue that checks: if currently we are in a super-call, then get the prototype to which the method belongs (depending on the info from the super call):
this.move is transformed into:
if (this.currentlyInSuper) ... // take from parent proto else return this.move(...) // take original
JFTR: It worked, now your code says: "you win". So, the hypothesis above is approved. gist.github.com/1367694
Anyway, that's said -- not for production sure, too much intermediate operations to keep the correct context in methods invocations.
Though, now I can almost (?) precisely say that even this issue with
calling this.move' with searching the
move' method no starting from
the beginning but in place where we currently are can also be solved
via a simple library -- w/o help from lower level. So it's again the
note that if the standard will provide such a sugar, it should make it
much better -- in other case, why do we need it?
Dmitry.
On 15.11.2011 17:34, Jake Verbaten wrote:
You fell for the broken super implementation trap jsfiddle.net/Wtx3E/1
By the way, forgot to mention. In dynamic languages it may be dependent. And it's actually a question what is a correct behavior -- early or late binding in this case. E.g. current Ruby (1.9.3-p0 Win) also shows "broken" in such an example:
class One def one two end def two print 'you win' end end
class Two < One def one super end def two print 'broken' end end
(Two.new).one # broken!
P.S.: though, I've tested the same example at work, and it seemed to me that it showed "you win". Don't know, perhaps I have some old version or Ruby at work. Anyway, in the newest version of Ruby the behavior used as shown above and it really depend what is wrong and what's not. Which way JS will choose -- it's another question; as we have seen, both variants can be implemented even in JS itself.
Dmitry.
<Just on the Rights of a bike-shedding :)>
R-proto-class is my quick experiment of yet another class lib for ES5: gist.github.com/1366953
Main features are:
Simple super calls (with mentioned before, but modified, "delete-restore" parent link); used only for classes.
using Object.create for inheritance (the main part of this lib variant) -- at user-level a programmer uses native Object.create
Class.new is a wrapper over Class.allocate and Class.initialize. I.e. overriding <UserClass>.allocate you may allocate different objects
It's just a lib, it's not proposed for standardization (you may even not to comment on this letter, just take a look for a curiosity); it's just shown again, that in both ES3 and ES5 we had and have lib-versions of such sugar, including good class-level super-calls. So again, if to talk about standardization, then the standardized version (whichever it will be) should be at least much better than all these libs. Including syntactically.