defender method syntax considered harmful
alex.buckley at oracle.com
Wed Sep 29 18:23:09 PDT 2010
On a general note, I certainly expect the feature set of "defender
methods" to evolve as java.util is upgraded. There will be examples
galore. We would strongly welcome any description of how people plan to
add to their interfaces in light of "defender methods" - will the
signatures of the abstract methods have a particular shape, will the
location of the default methods follow a particular rule, etc.
On 9/29/2010 5:41 PM, Per Bothner wrote:
>> 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.
> I don't think "conceivable" is good enough. We need examples.
> E.g. we might want to add a new method to Collection. Perhaps Set and
> List could use the same default implementation, while Map uses a different
> default. Then somebody defines a class that implements both Set and List.
> We want that to be OK, since they use the same default.
> The problem is I can't think where that might make sense. Presumably
> if you add a method to Collection, you need to add a default for it.
(I'm confused as to why you say "We want that to be OK" in one sentence
but then can't think of where it might make sense in the next.)
You add an abstract method to Collection, and define a default for it
there, then List and Set inherit the abstract method along with its
default. To invoke the abstract method on a variable of type List or Set
(and assuming the implementation does not implement the abstract method
itself), the runtime will have to inspect superinterfaces List and Set
and determine their defaults for the abstract method. Lo and behold,
they're the same! (Yes, List and Set really do have to be consulted; you
cannot jump straight to Collection. Inheritance happens.)
>> 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.
> I'm missing something. The JLS says "Changing the direct superclass
> or the set of direct superinterfaces of a class type will not break
> compatibility with pre-existing binaries, provided that the total set
> of superclasses or superinterfaces, respectively, of the class type
> loses no members."
Sure, the class type doesn't need to be recompiled. But its
superinterfaces do, since they're all getting a new superinterface! The
whole point is that a class's superinterfaces evolve independently, and
we can't demand they all know about each other in order to compare notes
>> 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?
> Why not? Note that the problem we're discussing is when adding the
> *same* default to *two* different interfaces, where neither extends the
> other. We still haven't seem an example of why you might want to
> do this
Language design is led by principle, not example. It should be clear
that, depending on a) the dominance of a hyperinterface (j.u.Collection
is rather dominant in j.u), b) the shape of the interface hierarchy, and
c) the availability of sensible defaults, there is the possibility of
common (i.e. unique) defaults across a class's superinterfaces.
> - or why (if you do find such an example) that adding a
> (possibly-artificial) hyperinterface would break binary compatibility.
It wouldn't break binary compatibility. It would just require more
recompilation than we believe is possible.
More information about the lambda-dev