defender method syntax considered harmful

Alex Buckley alex.buckley at oracle.com
Wed Sep 29 15:55:57 PDT 2010


On 9/29/2010 11:10 AM, Per Bothner wrote:
> So the syntax needs a lot stronger justification.  That this would
> "violate the long-held rule that "interfaces don’t have code"" doesn't
> mean anything - the whole point of this change is to *change* this
> rule so that interface *can* have code.

The goal is source-compatible interface evolution, not "method bodies in 
interfaces" per se. Now, a good way to get source-compatible interface 
evolution is via defaults for abstract methods. Specifying defaults by 
value (i.e. method bodies) is plausible, but with the introduction of 
method references in the language, it is also reasonable to think of 
specifying defaults by reference.

> So that leaves "by specifying the default by name rather than by
> value, it is easier for the runtime to identify whether two defaults
> are in fact the same method, which is important for conflict
> resolution." I'm missing something there:
> The runtime determined whether two defaults are the same method - by
> seeing if they're the same method: Defined in the same interface, with the
> same name and parameter list.  Is it because you might have two interfaces
> that might want to have the same default method?  That would seem a
> fairly rare use case, and can be easily solved by adding a new 
> super-interface.

Fairly rare? Maybe, or maybe not.

In general, the interfaces implemented by a class do not all define the 
same abstract method. If they do, then the interfaces are likely to have 
a common superinterface - what I might call a "hyperinterface". A 
hyperinterface is an important high-level interface with not only many 
possible implementations but also many possible subinterfaces. A good 
example in the Java SE API is java.util.Collection.

So, incompatible defaults are only going to be a problem where a class 
implements interfaces commonly under a hyperinterface. Because 
hyperinterfaces are few in number but rich in scope, it's certainly a 
problem to worry about. Yet, it's quite conceivable that subinterfaces 
of a hyperinterface will independently choose the same default for a 
given abstract method, especially high up in the interface hierarchy. We 
want to exploit that possibility. In finance terms, we get a good 
increase in alpha with minimal increase in beta.

You mention adding a common superinterface where interfaces wish to 
choose the same default for an abstract method. That more or less 
assumes global recompilation. But the challenge is precisely to preserve 
type soundness _under separate compilation_. That is, if a consumer 
(caller or implementer) can be compiled and run against a library, and 
then you add a default to a method in an interface in the library and 
recompile only that interface, does the consumer still compile and run? 
You don't get to recompile every class that implements the interface or 
calls it.

(It goes without saying that a consumer that compiles against the 
library, should run against the library.)

Thank you for raising your concern on the list, BTW.

Alex


More information about the lambda-dev mailing list