Proposal for extending functionality of default methods to allow general use

Lattie latsama at gmail.com
Wed Jan 30 13:41:43 PST 2013


While I readily bow your much broader breadth and depth of knowledge
on the topic, the fact remains that the language is still lacking in
the ability to succinctly express the idea of extending the
functionality of existing objects when one does not have control over
the types of those objects.  Such an ability would indeed be a boon to
the day to day productivity of the average programmer.

I do understand your argument in the abstract, but I feel that your
thinking should perhaps be tempered by greater consideration of the
practical value of such an ability.  Is it really the case that there
is *no* good way to get those benefits within the framework of the
current language design?

My proposal is really just another form of expressing the programmers
intent more concisely.  Many of the recent improvements to the
language came from just such an approach.

In other words, while it's true that I could get the "same" effect by
just writing a method:

static void printListSize(List<T> list)
{
   System.out.println("The size of this list is: " + list.size());
}

and then just calling that method as needed, it would be *better*
(less burden on the programmer), if I could express that in terms of
an extension method on the List interface itself...

The most compelling part of your counter argument is your point about
the lack of virtualness of my proposal.  I agree that is a big
deficiency of this proposal...  but, isn't there *some* way to get the
benefit that I'm seeking?  Help me out here!  lol

As far as the principled decision about API owners owning their APIs
"for better or worse"... well, all to often these days it turns out to
be "worse" rather than "better".  I mean how often do you come across
a really *well* designed Java library?  A lot of the language
evolution over time has been the job of reengineering/replacing older
and less well designed libraries (and then replacing the new ones in
turn with even newer ones).  As a programmer I often find myself
frustratingly hamstrung by deficiencies in an API that could (should)
have been designed better.

Might there not be a higher principle: Respect the API developer, but
trust in and serve the interests of the end-user programmer above all.

In any case, thanks for taking the time to consider and comment on the
original proposal! :)  Very educational.



On Wed, Jan 30, 2013 at 1:07 PM, Brian Goetz <brian.goetz at oracle.com> wrote:
> tl;dr version: No.
>
>
> This is ground that was covered a long time ago.  Let me first compare with
> C# since this is a most proximate example of use-site extension methods.
>
> Our extension methods are /declaration-site/ and /virtual/.  By contrast, C#
> extension methods are /use-site/ and /static/.  Further, our extension
> methods are added to /classes/, whereas C# extension methods are added to
> /types/.
>
> There are some benefits to each; C# users are jealous of the virtual-ness of
> our extension methods, and Java developers will be jealous when they realize
> that you can't add a sum() method to List<Integer> without adding it to all
> Lists.  But the issue you raise -- being able to monkey-patch new methods
> into someone else's classes -- is not a clear winner in either direction.
>
> Your argument seems to be "use site extension seems really convenient."  I
> don't dispute the convenience of this, and C# has done some impressive
> things with their extension methods (reified generics helped).  However, our
> decision was a principled decision -- API developers should own their APIs,
> for better or worse.
>
> Allowing use-site extension also undermines virtualness, which is also
> tremendously valuable.  Given how much nastiness has its root in staticness,
> do we want to add a language mechanism that engenders more staticness?
> Nope.
>
> Now, your proposal is not exactly like C#'s.  While it is short on detail,
> it appears to be quite similar to the "Expanders" paper by Milstein et al:
> http://www.cs.ucla.edu/~todd/research/oopsla06a.pdf. This was one of the
> many models we explored before settling on the current one.
>
>
>
> On 1/30/2013 3:33 PM, Lattie wrote:
>>
>> Currently default methods can be used by the author of an Interface to
>> extend the functionality of that Interface without requiring the
>> rewriting of code that already implements that Interface.
>>
>> That's a great feature, but it would be even greater if end-user
>> programmers were enabled to extend the functionality of existing
>> Interfaces.  (As it is, the feature is to be used by the *authors* of
>> Interfaces, but not by the *users* of the Interfaces.)
>>
>> This can be accomplished as follows:
>>
>> 1) Introduce the concept of an 'Extension Interface', which is an
>> Interface that derives from an existing interface, and then *only*
>> adds 'default' methods.
>>
>> 2) Allow the casting of an object that implements a given Interface
>> into an instance of any 'Extension Interface' derived from the
>> original Interface.
>>
>> This would allow end users to express additional desired behavior for
>> existing libraries in a simple, intuitive and straightforward way.  It
>> does not require any changes to the Java language syntax, only the
>> recognition by compilers that casting an object into an Extension
>> Interface type is ok to do.
>>
>> For example, consider the following code:
>>
>> ### MyExtendedList.java
>>
>> import java.util.*;
>>
>> // This is an 'Extension Interface' of List<T>
>> public interface MyExtendedList<T> extends List<T>
>> {
>>     default void printSize()
>>     {
>>        System.out.println("The size of this list is: " + size());
>>     }
>> }
>>
>> ### Test.java
>>
>> import java.util.*;
>>
>> public class Test
>> {
>>     public static void main(String[] args)
>>     {
>>        List<String> strings = new ArrayList<>();
>>
>>        strings.add("foo");
>>        strings.add("bar");
>>
>>        MyExtendedList<String> myStrings = (MyExtendedList<String>)strings;
>>
>>        myStrings.printSize();
>>     }
>> }
>>
>> ######
>>
>> With the proposed extension, this code would print out:
>>
>> The size of this list is: 2
>>
>> As it is, an exception is thrown:
>>
>> Exception in thread "main" java.lang.ClassCastException:
>> java.util.ArrayList cannot be cast to MyExtendedList
>>
>> The reason it would always be safe to allow the cast to succeed is
>> that any 'Extension Interface' is always defined only in terms of the
>> already existing public interface methods that exist on the Interface
>> from which it derives.
>>
>> Another way to look at it is that any object that implements a given
>> Interface also *implicitly* implements any and all 'Extension
>> Interfaces' that are based on the original Interface.  Under this
>> view, even the cast could be eliminated and the object assigned
>> directly.
>>
>> The benefits to end user programmers of adding this new ability to
>> effectively extend the behavior of existing classes simply by casting
>> them would be profound, and most welcome.
>>
>> Since no changes to the language are required, there would be no
>> adverse impact on those not wishing to make use of the feature.
>>
>


More information about the lambda-dev mailing list