Making "super" work outside a literal?
brendan at mozilla.com
Sat Jun 25 14:42:39 PDT 2011
On Jun 25, 2011, at 2:29 PM, Axel Rauschmayer wrote:
>>> That would be enough. I guess I’m suggesting then to implement “super” like CoffeeScript does. Wouldn’t that be simpler?
>> As my next message showed, Allen's http://wiki.ecmascript.org/doku.php?id=harmony:object_initialiser_super is like CoffeScript as far as dynamic vs. lexical binding goes.
>> It differs in the same way that the Harmony classes proposal differs from CoffeeScript: you call super.foo() or super.bar() from method foo. You cannot just call super() from method foo to invoke the superclass's method foo, and only that method.
>> Should we really constrain super calls in methods to be only of the same-named method in the superclass? Conciseness is better but the restriction seems worse. Is it necessary in Ruby or CoffeeScript?
> Oh. I have never seen super used like in CoffeeScript before (which is why I haven’t even noticed it in the CoffeeScript code that I have looked at, so far). I am strongly in favor of the more capable Harmony solution.
There are deeper waters here. See http://www.artima.com/intv/nonvirtualP.html (via http://geekswithblogs.net/madhawa/archive/2006/09/17/91418.aspx) where Anders Hejlsberg says:
"There are two schools of thought about virtual methods. The academic school of thought says, "Everything should be virtual, because I might want to override it someday." The pragmatic school of thought, which comes from building real applications that run in the real world, says, "We've got to be real careful about what we make virtual."
When we make something virtual in a platform, we're making an awful lot of promises about how it evolves in the future. For a non-virtual method, we promise that when you call this method, x and y will happen. When we publish a virtual method in an API, we not only promise that when you call this method, x and y will happen. We also promise that when you override this method, we will call it in this particular sequence with regard to these other ones and the state will be in this and that invariant.
Every time you say virtual in an API, you are creating a call back hook. As an OS or API framework designer, you've got to be real careful about that. You don't want users overriding and hooking at any arbitrary point in an API, because you cannot necessarily make those promises. And people may not fully understand the promises they are making when they make something virtual."
The rest is well worth reading.
If subclass foo can call super.bar() and the superclass bar calls this.foo(), what happens? Java without final before the method is like C++ with virtual before the method. The subclass foo() will be called.
Often, especially if you buy Anders' arguments, you want what Peter Michaux has called a sideways call from the superclass bar, to lexical foo(). You can do that and prevent overrides from subclasses. This is not always the right thing, but it seems like the right default.
I asked Jeremy Ashkenaz about CoffeeScript's super()-only restriction, modeled on Ruby. He wrote back:
"The rationale [is] that if you're overriding an implementation of a method, you're responsible for preserving the proper API at that point. By reaching behind the back of an overridden function, and calling its parent implementation without going through it, you're saying that the override was done wrong, or doesn't preserve the API you need.
This is basically the difference between Java super and Ruby super.
I'd be very curious to see an example of an inheritance pattern that relies on being able to call super() against "other" methods."
> I guess the difference between CoffeeScript and Harmony is that CS knows the name of the class inside a class body during compilation, whereas in an object literal, you need to attach a property to a method which points to the object.
To the object's [[Prototype]], if you mean the internal property referenced by 'super' in the method.
> By looking at JS code generated from CS code, it seemed that the CS approach was somehow simpler, but that was an illusion.
Looks like more code in the generated case to me. More != simpler, even if it may be no more complex.
It seems to me that we missed something in jumping on the Java (or was it C#? But C# has non-virtual, or Java final, methods by default, unlike Java) bandwagon with the super.foo or super.bar() from foo design.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the es-discuss