7

We have default methods that were also referred to as defender methods and 'virtual extension methods'.

While I appreciate the tremendous value of default methods (that in some aspects are even more powerful than their C# counterparts), I wonder what was the decision against allowing to extend existing interfaces without access to their source code.

In one of his answers here in SO Brian Goetz mentioned that default methods are very much designed for convenience as well as interface evolution. So if we write an interface, we can stuff all kinds of utility methods there that we would normally have to place in a separate class. So why not go the extra mile and allow it for interfaces not under our control?

user1803551
  • 12,965
  • 5
  • 47
  • 74
Vitaliy
  • 8,044
  • 7
  • 38
  • 66
  • 1
    I have no idea, but I know what would make me mad with such a feature: see a method Foo.bar() used in some code, browse the javadoc of Foo, not seeing any mention of the bar() method. – JB Nizet Apr 06 '15 at 06:33
  • I don't think it is opinion based. I am asking what were the opinions- there is a difference. These considerations probably appear in certain mailing lists (though I did not find any) or in the minds of the Java architects, that monitor SO for these kind of questions. See "http://stackoverflow.com/questions/28459498/why-are-java-streams-once-off" as an example where Stuart Marks has answered me. – Vitaliy Apr 06 '15 at 13:05
  • 2
    For what it's worth, I would be terrified of allowing people to add arbitrary methods to interfaces they don't control; library clutter is a serious issue that takes constant effort to avoid, and the best-designed libraries tend to be deliberately minimal in their API. – Louis Wasserman Apr 06 '15 at 18:46
  • 4
    This was driven by a philosophical belief: _API designers should control their APIs_. Monkey-patching into existing APIs undermines an API designers control over their API. (Also: using "extension methods" to mean "what C# calls extension methods" is somewhat obfuscatory; default methods *are* extension methods too. C# chose "static" and "use-site" for their extension methods; we chose "virtual" and "declaration-site". (Also note: virtual is clearly more powerful here, so the glass is half full as well as half empty for folks who love the C# interpretation.) – Brian Goetz Apr 06 '15 at 18:57
  • @BrianGoetz, thanks. I wish you could post this as an answer though. Can you vote for reopening the question? – Vitaliy Apr 07 '15 at 06:20

2 Answers2

11

This was driven by a philosophical belief: API designers should control their APIs. While externally injecting methods into APIs is surely convenient, it undermines an API designers control over their API. (This is sometimes called "monkey-patching".)

On the terminology: what C# calls "extension methods" is merely one form of extension method, not the definition of extension method; Java's default methods are also extension methods. The main differences are: C# extension methods are static and are injected at the use-site; Java's are virtual and declaration-site. Secondarily, C# extension methods are injected into types, whereas Java's default methods are members of classes. (This allows you to inject a sum() method into List<int> in C# without affecting other List instantiations.)

It's natural, if you have gotten used to the C# approach, to assume that this is the "right" or "normal" or "real" way to do it, but really, it's just one of many possible ways. As other posters have indicated, C# extension methods have some very serious drawbacks compared to Java's default methods (for example, poor reflective discoverability, poor discoverability through documentation, not overrideable, require ad-hoc conflict-management rules). So the Java glass is well more than half-full here by comparison.

Brian Goetz
  • 90,105
  • 23
  • 150
  • 161
8

While Brian Goetz mentions that default methods will also be used for convenience, it does not mean that it was the first goal of default methods.

As a reminder: default methods exist in order to support interface evolution, something that was extremely badly needed in the face of the introduction of lambdas (as the introduction of lambda-using methods often meant that new methods should be added).

You are writing your post as if there was no drawback to extension methods as they exist in C#, however:

  • Extension methods have an enormous discoverability issue:

    • They do not appear in the class documentation;
    • They are not exposed by reflecting over the class;
    • When you see a usage of an extension method in code, you have no way of knowing where the extension method comes from without an IDE;
  • Extension methods, by their very nature, do not allow some of the standard disambiguation mechanisms:

    • What happens when you use an extension method to define an overload for a class method, and that overload, or a similar extension method, is defined by the author of the class? Case 1: Your code switches over to using the new method with a simple recompilation; Case 2: Your code does not compile anymore;
    • Because of that, I do not recommend defining putting extension methods in a namespace that you do not control, as it can make such issues intractable. However, doing that means that extension methods for types you do not control become even harder to discover;
  • Extension methods are inflexible:

    • Once an extension method is defined by a library, there is no way for clients of that library to change or tweak that extension method's implementation;
    • If a client defines an extension method for a type he does not control, he will have a compatibility issue on his arms the day that the library defines the same extension method. The likelihood of that depends on what the extension method does, and the evolution policy of that library.

Of these three drawbacks, default methods as they exist in Java 8 have none of them.

You should note that, the big reason for the inclusion of extension methods in C# was to enable LINQ. As Java went with another design for its streams, I do not see the Java language designers adding them as a matter of course.

Brian Goetz
  • 90,105
  • 23
  • 150
  • 161
Jean Hominal
  • 16,518
  • 5
  • 56
  • 90
  • 2
    I wouldn't say that default methods exist mainly in order to make functional interfaces applicable to more existing interfaces. They exist mainly to be able to add new methods to existing interfaces without breaking backward compatibility with existing implementations. – JB Nizet Apr 06 '15 at 07:29
  • 4
    For clarity, I'll add that the first two drawbacks stem from being injected externally rather than being part of the class definition; the third corresponds to C#'s extension methods being static rather than virtual. – Brian Goetz Apr 06 '15 at 22:50