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