Virtual extension methods -- a strawman design

Howard Lovatt howard.lovatt at gmail.com
Mon May 24 01:06:02 PDT 2010


Just to clarify my reading of the spec:

If we initially have:

interface IA {}
interface IB {}
class A implements IA {}
class B implements IB {}
class AB implements IA, IB {}

Then modify:

interface IA { extension int m() default IAs.m; }
interface IB { extension int m() default IBs.m; }

And we don't recompile the classes A, B, and AB then A and B will work
just fine and as expected, however AB will throw an exception if m is
called.

I think that this combination of:

1. Adding the same extension method signature to multiple interfaces
2. Not recompiling classes that implement more than one of these interfaces
3. Calling the extension method on the non re-compiled classes

Will be reasonably rare, hence I thought the specification was reasonable.

Another option would be for the class loading to fail for AB, since m
is ambiguous. I would have thought that either AB failing to load (I
suggested this for my Trait proposal) or the runtime exception
proposed in the Oracle document are reasonable behaviors.

On 24 May 2010 15:01, Neal Gafter <neal at gafter.com> wrote:
> Both default behaviors can be improved by recognizing that these
> different methods don't have to resolve to the same implementation:
>
> If both interface A and interface B declare defender methods with the
> same signature, there is no ambiguity in a class C that extends A and
> B.  Invoking the method through C is a compile-time error (ambiguous),
> invoking through A gets A's behavior, and invoking through B gets B's
> behavior.  There is no need to guess how rare these cases might be.
>
> On Sun, May 23, 2010 at 5:52 PM, Howard Lovatt <howard.lovatt at gmail.com> wrote:
>> Alex Blewitt said:
>>
>>> This is the classic 'diamond problem' that is experienced with multiple implementation inheritance.
>>> Unfortunately, the proposal document (http://cr.openjdk.java.net/~darcy/DefenderMethods.pdf)
>>> brushes this under the covers (5.1) with a 'should throw an exception' at this point. This is
>>> pretty silent, outside of any compiler warnings, and is definitely a change of behaviour.
>>
>> Section 4.2 seems to cover what happens.
>>
>> "4.2. Resolving ambiguity
>> If the class implements multiple extended interfaces, both of which
>> provide a default
>> implementation for the same method name and signature, the
>> implementing class MUST
>> provide an implementation.  (This is expected to be a quite unusual
>> case.)  The existence
>> of the InterfaceName.super.methodName() syntax makes it easy for the
>> class to choose
>> one of the defaults.  (We might choose to relax this restriction if
>> both interfaces provide the same default.)"
>>
>> This solution is the normal solution for traits, i.e. programmer has
>> to resolve the issues.
>>
>> Alex Blewitt said:
>>
>>> public class A implements DataStructure {
>>>   public boolean filter(FilterSam filter) {...}
>>> }
>>> // Later, someone makes the change:
>>> public interface DataStructure {
>>>   extension DataStructure filter(FilterSam filter) default Default.filter;
>>> }
>>
>> When A is net recompiled there is a compiler error. If A is not
>> recompiled there is a link error. See section:
>>
>> "5.1. Resolving ambiguity
>> In the unlikely case that the VM attempts to load a class that
>> implements multiple
>> extended interfaces that have a common defender method but with
>> different defaults, the
>> VM should not attempt to resolve the ambiguity automatically.
>> Instead, it should
>> generate a bridge method that throws UOE or similar exception.  We
>> expect this situation
>> to be rare."
>>
>> I would agree with the assessment that this will be rare and therefore
>> catching the error is sufficient.
>>
>>  -- Howard.
>>
>>
>



-- 
  -- Howard.


More information about the lambda-dev mailing list