Default methods in multiple parents
Brian Goetz
brian.goetz at oracle.com
Sun Apr 7 09:19:35 PDT 2013
Yes, the model handles this just fine.
The method foo()Integer in II overrides the method foo()Number in NI.
So foo()Number will never be inherited into a class that implements II,
no matter how many times you say "inherits NumberInterface".
So in your example, NC inherits foo()Number from NI, but IC inherits
foo()Integer from II.
On 4/7/2013 11:41 AM, Zhong Yu wrote:
> Consider this example of diamond inheritance
>
> interface NumberInterface
> {
> default Number foo(){ return 1; }
> }
>
> interface IntegerInterface extends NumberInterface
> {
> default Integer foo(){ return 2; }
> }
>
> static class NumberClass implements NumberInterface
> {
> }
>
> static class IntegerClass extends NumberClass implements
> IntegerInterface
> {
> }
>
> The code compiles and works. However I am a little uncertain. My doubt is
> this: arguably, NumberClass "contains" a method `Number foo()`.
So, your question is over the interpretation of the "class wins" rule.
Your argument is that because NC "has" a member foo()Number, shouldn't
that count? The answer is: no. We consider the *explicit* members of
the superclass chain, and then for each class, we start anew looking at
interfaces to "fill in" any missing implementations.
> IntegerClass skips that `foo()` method in its super class and inherits a
> `foo()` from a super interface, is that justifiable? Actually, if we copy
> NumberInterface.foo(){} into NumberClass,
>
> static class NumberClass implements NumberInterface
> {
> public Number foo(){ return 1; }
> }
>
> a seemingly innocent move, suddenly IntegerClass cannot compile anymore
> (due to incompatible return types).
That is the correct and expected behavior; your change has demanded that
IC have an Integer-bearing foo() method, but it has none (because class
methods take priority over interface methods). But blaming default
inheritance is misplaced. Adding a concrete method to *any* non-final
class always carries the risk of this being a source-incompatible change
for subclasses. This is true without defaults and even without
interfaces involved.
Once you declare foo()Number in the concrete class, you've changed the
inheritance. Subclasses would have to explicitly override and choose
what to do (super-call to class parent; super-call to interface parent;
something else.)
> Could someone confirm that the original example works correctly according
> to the spec? (I hope so since I'm depending on it.)
In your example, NC inherits implementation from NI and IC inherits
implementation from II. If NC were to explicitly override foo(), so
would IC.
More information about the lambda-dev
mailing list