Making "super" work outside a literal?

Axel Rauschmayer axel at rauschma.de
Sat Jun 25 17:50:01 PDT 2011


> 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.

It probably makes sense to distinguish between preventing overriding and static dispatch:
- AFAIK, Java always does dynamic dispatch and has virtual instance methods. final “merely” prevents overriding. But that does indeed reduce the hooks that Hejlsberg talks about.
- With static dispatch, you can override which also might lead to unintended effects.

The problem seems to be that a public method plays two roles: It is an interface to the clients of a class, but also an interface to the methods of the class itself. In Java, when I want a method to exclusively play the latter role then I make it private. Maybe a method should never call sibling public methods, only private ones.

I’ve done overriding to contribute to an API, but also to patch something (to avoid copy-pasting code – a hack, but still needed). The former is part of the design, the latter is necessary for use cases that cannot be predicted. I’m less paranoid about the wrong method being overridden than about a method that one wants to be overridden not being called from the overriding method. That is, I’m usually paranoid about clients not adhering to the protocol of my API. Thus, I like anything that helps me with expressing the protocol and ensuring that no mistakes are made. I only want to enforce something if it helps the previous two goals. In this vein, “private by naming convention” is enough for me. Obviously, different rules apply when security is a concern.

How about a marker saying “this method can be overridden” (enable, don’t prevent)? If a method does not have this marker it could still be overridden, but one would have to expend extra effort to prove that one knows what one is doing (similar to suppressing generics-related type warnings in Java).

I’m not sure how much of the above applies to JavaScript, though, because you need dynamic dispatch to make shared methods work. And things being so simple and flexible is part of JavaScript’s charm.


> 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."

A very good point. AFAIK, Common Lisp only has next-method calls and no generic super calls. [As an aside, from what I have seen of Common Lisp, it is a great mix of dynamic language features and static language features.]

-- 
Dr. Axel Rauschmayer

axel at rauschma.de
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110626/f70bdf53/attachment-0001.html>


More information about the es-discuss mailing list