Proposal for extending functionality of default methods to allow general use
Brian Goetz
brian.goetz at oracle.com
Wed Jan 30 13:07:32 PST 2013
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