This question already has answers here:
When to use: Java 8+ interface default method, vs. abstract method
(16 answers)
Closed 7 years ago.
Why We need Defender methods in interfaces in java 8 as we already have abstract classes.I found various answers on internet like:
To add external functionality
But Abstract class is for partial Abstraction where as our interface is actually a pure abstract class so why their is a default method inside an interface?
The problem with sharing functionality by placing it in an abstract base class is that a class can derive from exactly one base class. This is a limitation in cases when you would like to inherit functionality from more than one base.
Sharing functionality through an abstract base class may also become a problem when you need to implement an interface from a class that already has a base class. In this case you cannot derive your new class at all, because you must pick one of the two bases, when presumably you want both.
Default methods solve this problem with elegance: placing your common implementation into the default method allows you to share the code without limitations.
You can think of the main difference between default methods and inheriting an abstract class as the difference between sharing functionality horizontally across siblings that implement the same interface, or vertically among children that inherit from the same base class.
Here is an examoke: consider an interface that looks like ResultSet of JDBC, which has two ways of accessing the same column - by name and by index. The interface could be coded up like this:
interface ResultSet2 {
int findColumn(String columnLabel);
String getString(int index);
long getLong(int index);
default long getLong(String columnLabel) {
return getLong(findColumn(columnLabel));
}
default String getString(String columnLabel) {
return getString(findColumn(columnLabel));
}
}
Anyone implementing ResultSet2 would have to implement three methods, and get the remaining two for free. They would have an option to provide an alternative implementation, but that would be optional.
The main reason behind defender methods is to be able to extend long-existing interfaces with new functionality, without breaking the existing code. Particulary with Java 8 lamba expressions they introduced a lot of new methods on collection interfaces, like Iterable.forEach. With providing default methods, existing classes implementing the Iterable interface dont have to be altered to use in Java 8 environment.
The original intent was to compete with C#'s extension methods. Given core methods of an interface, e.g. get(), set() in List, extention methods (e.g. sort()) can be defined and implemented.
Java guys argued that it would be better to declare such methods on the interface itself, rather than in external places; so that the methods could be overridden by subtypes, providing optimal implementations per subtype. (They also argued that such methods should be controlled by the interface authors; this is rather a soft point)
While default methods can be added to existing interfaces, it is very risky of breaking existing 3rd party subtypes, particularly for very old types like List with lots of subtypes in the wild. Therefore very few default methods were added to existing core Java APIs. See this question.
For new interfaces, default method is a very valuable tool for API designers. You can add a lot of convenience methods to an interface, for example, Function.compose(). Subtypes only need to implement abstract/core methods, not default methods (but they can if they want to).
I disagree with the idea that default methods can "evolve" interfaces. They do not change the core semantics of an interface, they are just convenience methods (in the form of instance method).
And default methods should be carefully designed up-front when the interface is designed; as said, it is very risky to add default methods afterwards.
C#'s extension method allows 3rd party to add convenience methods; this is very nice, and there is no reason why Java couldn't introduce something similar in future.
Related
Java 8 has included a new feature called Defender methods which allows creation of default method implementation in interface.
Now first of all this is a huge paradigm shift for all condensed programmers in Java. I viewed a JavaOne 13 presentation given by Brian Goetz where he was discussing about the new stream() and parallelStream() implementations in Collections library.
For adding new methods in Collection interface, they could not have just added a new method without breaking the previous versions. So he told that for catering this a new feature of Default methods was added.
public interface SimpleInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork(){
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
Now my question is basically that are default methods just helpful when needed to add new methods to interface without breaking client code? Or are there some other uses to it too?
Besides having the possibility of adding methods to the interface in future versions, there is the important point of allowing an interface to stay a functional interface even if it has more than one method.
A functional interface has only one non-default abstract method which can be implemented via a lambda expression. One example is the Predicate interface which has only one abstract method (test) while providing default methods for negating a Predicate or combining it with another Predicate. Without default methods these methods had to be provided in another utility class like the pre-Java 8 Collections class (as you don’t want to give up the possibility of lambda implementations for such an interface).
As you said, the main motivation was allowing the evolution of existing interfaces.
However there are reasons why you'd want to use them in brand new interfaces as well:
One such reason is methods that can easily be implemented using the other (non-default) methods of the interface. Using default methods for this reduces the need for Foo-interface/AbstractFoo-base-implementation combinations (see AbstractList for example).
While this does not create an entirely new field, it means that you can have end-user-friendly interfaces (with lots of useful methods), still keeping it simple to implement.
There was a problem with interfaces that they were not open to extension, which means if there was a need to add new method to an interface it would have broken the existing implementation of these interfaces. Thus it was imperative that all the classes implementing that interface had to provide implementation for the newly added method, even if the method was not needed. Thus interfaces were not easy to evolve.
One example that comes to mind is Java MapReduce API for Hadoop, which was changed in 0.20.0 release to favour abstract classes over interfaces, since they are easier to evolve. Which means, a new method can be added to abstract class (with default implementation), with out breaking old implementations of the class.
With the release of Java 8, it is now possible to add default method in interfaces also, thus making them easier to evolve too. With the addition of default method to an interface, addition of new method, to even an interface will not break the pre-existing code.
For adding new methods in Collection interface, they could not have
just added a new method without breaking the previous versions.
Yes they could have done this but Let's think from API designer perspective for e.g. Collection Library is used by some libraries like apache-commons, guava etc and which instead are used by many java projects. Now imagine just by adding one new method in Collection interface will break entire chain of projects.
Now my question is basically that are default methods just helpful
when needed to add new methods to interface without breaking client
code? Or are there some other uses to it too?
Motivation/Need for Default Methods
API Evolution in compatible way
The initial purpose of introducing default methods was to make collections library backward compatible. This library was modelled as a deep hierarchy of interfaces, including prominent members such as Collection, List, Map, and Set. They needed to be enriched to make lambdas truly useful for everyday programming.
To make Collections library lambda rich, java architects could have
refactored them to support lambda but it was a far from a good
solution as it will break all the all existing Java deployments and
countless 3rd party libraries extending the Collections hierarchy
Instead java architects thought to introduce default methods capabilities for backward compatibility.
Use cases of Default Methods
One important use case is to aid functional thinking in java. A functional interface with default methods is a pure behaviour-only construct. It cannot hold state. This aligns your thinking with functional programming and allows you to take advantage of what the programming model has to offer
Optional Methods : There are classes in java that implement an interface but leave empty method implementations for e.g. Iterator interface. It defines hasNext and next but also the remove method. Prior to Java8 remove was ignored because the user didn't want to use that capablity. Therefore many classes implementing Iterator interface would have empty implementation of for remove which is unnecessary boiler plate code. With default methods we can provide a default implementation for such methods, so concrete classes don't need to explicitly provide an empty implementation.
Default methods helps in resolving Multiple inheritance of behaviour in java. Before Java8, there was support for Multiple inheritance of Type only and now with the help of default methods we can have multiple inheritance of behaviour.
For e.g.
Java 8 has three rules for resolving conflicts brought upon by
multiple inheritance when ambiguous:
First, an explicit method declaration in the class or a superclass takes priority over any default method declaration.
Otherwise, the method with the same signature in the most specific default providing interface is selected.
Finally, if there is still conflict, you have to explicitly override the default methods and choose which one your class should choose.
In Conclusion Default methods offer a brand new way to design objects.
References :
Java8 In Action
Functional Java: A Guide to Lambdas and Functional Programming in Java 8
default methods made possible the functional programming concept. For functional programming type code we need only one abstract method .
Also adding an method in interface will not made it compulsory for all the classes implementing an interface. Simplified the coding practise
Learning java 8 default methods .
This link like any other resource on internet says
In ‘the strictest sense’, Default methods are a step backwards because
they allow you to ‘pollute’ your interfaces with code. But they
provide the most elegant and practical way to allow backwards
compatibility. It made it much easier for Oracle to update all the
Collections classes and for you to retrofit your existing code for
Lambda.
My understanding is that java 8 dev/designers provided the default method in interfaces so that all implementing class does not have to unnecessarily
override same behavior, hence provide backward compatibility. For example :- if ForEach method would not have been default method, every collection implementing class had to implement it. Agreed .
To overcome that we could have had one class providing implementation of these default methods and then implementing class like arraylist etc could
have extended that. This way we could have statisfy both java fundamentals i.e reusability and abstraction i.e keeping the interface pollution less
I am sure java 8 dev/designer have already thought about this as they are much more learned and i am missing something here. Can someone help here so that we developers can also be on top of it as this major change?
Before Java 8, interfaces could have only abstract methods. The implementation of these methods has to be provided in a separate class. So, if a new method is to be added in an interface then its implementation code has to be provided in the class implementing the same interface.
To overcome this issue, Java 8 has introduced the concept of default methods which allow the interfaces to have methods with implementation without affecting the classes that implement the interface.
The default methods were introduced to provide backward comparability so that existing interfaces can use the lambda expressions without implementing the methods in the implementation class. Default methods are also known as defender methods or virtual extension methods.
To overcome that we could have had one class providing implementation of these default methods and then implementing class like arraylist etc could have extended that.
Your suggestion would work only for standard JDK classes (since they usually extends some base classes such as AbstractCollection and AbstractList, were the implementation of the new methods can be added).
What about custom classes that implement JDK interfaces? If, for example, you have a class that implements List but doesn't extend some JDK List implementation, you should be able to switch to Java 8 without having to implement new methods in your class.
With default implementations of new methods in the List interface, you don't have to touch your custom class. You can later add a custom implementation to those methods if you are not satisfied by the default implementation.
If there is a requirement to add new method to an interface, clients which use existing interface will be broken as classes needs to implement all methods in the interface.
In this scenario, default and static methods can be used. These methods can have body and clients don't need to implement them, so existing implementations work without any changes.
For example, if you want to enhance interfaces to add methods which accept lambda expressions, you can use default methods.
Java 8 has included a new feature called Defender methods which allows creation of default method implementation in interface.
Now first of all this is a huge paradigm shift for all condensed programmers in Java. I viewed a JavaOne 13 presentation given by Brian Goetz where he was discussing about the new stream() and parallelStream() implementations in Collections library.
For adding new methods in Collection interface, they could not have just added a new method without breaking the previous versions. So he told that for catering this a new feature of Default methods was added.
public interface SimpleInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork(){
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
Now my question is basically that are default methods just helpful when needed to add new methods to interface without breaking client code? Or are there some other uses to it too?
Besides having the possibility of adding methods to the interface in future versions, there is the important point of allowing an interface to stay a functional interface even if it has more than one method.
A functional interface has only one non-default abstract method which can be implemented via a lambda expression. One example is the Predicate interface which has only one abstract method (test) while providing default methods for negating a Predicate or combining it with another Predicate. Without default methods these methods had to be provided in another utility class like the pre-Java 8 Collections class (as you don’t want to give up the possibility of lambda implementations for such an interface).
As you said, the main motivation was allowing the evolution of existing interfaces.
However there are reasons why you'd want to use them in brand new interfaces as well:
One such reason is methods that can easily be implemented using the other (non-default) methods of the interface. Using default methods for this reduces the need for Foo-interface/AbstractFoo-base-implementation combinations (see AbstractList for example).
While this does not create an entirely new field, it means that you can have end-user-friendly interfaces (with lots of useful methods), still keeping it simple to implement.
There was a problem with interfaces that they were not open to extension, which means if there was a need to add new method to an interface it would have broken the existing implementation of these interfaces. Thus it was imperative that all the classes implementing that interface had to provide implementation for the newly added method, even if the method was not needed. Thus interfaces were not easy to evolve.
One example that comes to mind is Java MapReduce API for Hadoop, which was changed in 0.20.0 release to favour abstract classes over interfaces, since they are easier to evolve. Which means, a new method can be added to abstract class (with default implementation), with out breaking old implementations of the class.
With the release of Java 8, it is now possible to add default method in interfaces also, thus making them easier to evolve too. With the addition of default method to an interface, addition of new method, to even an interface will not break the pre-existing code.
For adding new methods in Collection interface, they could not have
just added a new method without breaking the previous versions.
Yes they could have done this but Let's think from API designer perspective for e.g. Collection Library is used by some libraries like apache-commons, guava etc and which instead are used by many java projects. Now imagine just by adding one new method in Collection interface will break entire chain of projects.
Now my question is basically that are default methods just helpful
when needed to add new methods to interface without breaking client
code? Or are there some other uses to it too?
Motivation/Need for Default Methods
API Evolution in compatible way
The initial purpose of introducing default methods was to make collections library backward compatible. This library was modelled as a deep hierarchy of interfaces, including prominent members such as Collection, List, Map, and Set. They needed to be enriched to make lambdas truly useful for everyday programming.
To make Collections library lambda rich, java architects could have
refactored them to support lambda but it was a far from a good
solution as it will break all the all existing Java deployments and
countless 3rd party libraries extending the Collections hierarchy
Instead java architects thought to introduce default methods capabilities for backward compatibility.
Use cases of Default Methods
One important use case is to aid functional thinking in java. A functional interface with default methods is a pure behaviour-only construct. It cannot hold state. This aligns your thinking with functional programming and allows you to take advantage of what the programming model has to offer
Optional Methods : There are classes in java that implement an interface but leave empty method implementations for e.g. Iterator interface. It defines hasNext and next but also the remove method. Prior to Java8 remove was ignored because the user didn't want to use that capablity. Therefore many classes implementing Iterator interface would have empty implementation of for remove which is unnecessary boiler plate code. With default methods we can provide a default implementation for such methods, so concrete classes don't need to explicitly provide an empty implementation.
Default methods helps in resolving Multiple inheritance of behaviour in java. Before Java8, there was support for Multiple inheritance of Type only and now with the help of default methods we can have multiple inheritance of behaviour.
For e.g.
Java 8 has three rules for resolving conflicts brought upon by
multiple inheritance when ambiguous:
First, an explicit method declaration in the class or a superclass takes priority over any default method declaration.
Otherwise, the method with the same signature in the most specific default providing interface is selected.
Finally, if there is still conflict, you have to explicitly override the default methods and choose which one your class should choose.
In Conclusion Default methods offer a brand new way to design objects.
References :
Java8 In Action
Functional Java: A Guide to Lambdas and Functional Programming in Java 8
default methods made possible the functional programming concept. For functional programming type code we need only one abstract method .
Also adding an method in interface will not made it compulsory for all the classes implementing an interface. Simplified the coding practise
This question already has answers here:
Purpose of Default or Defender methods in Java 8
(5 answers)
Closed 8 years ago.
I'm taking a look to Java 8 news compared to 7 and in addition to very interesting things like lambdas or the new time framework, i found that a new feature(?) was introduced: default methods.
I found the following example in this article:
public interface Math {
int add(int a, int b);
default int multiply(int a, int b) {
return a * b;
}
}
It seems very strange to me.
Above code looks like an abstract class with an implemented method. So, why to introduce default methods in an interface? What is the actual advantage of this approach?
In the same article I read this explaination:
Why would one want to add methods into Interfaces? We’ll it is because interfaces are too tightly coupled with their implementation classes. i.e. it is not possible to add a method in interface without breaking the implementor class. Once you add a method in interface, all its implemented classes must declare method body of this new method.
Well this doesn't convince me at all. IMHO I believe that when a class implements an interface obviosly must declare methods body for each method in it. This is surely a constraint, but it's also a confirm of its "nature" (if you understand what I mean...)
If you have common logic to every inheriting class you'll put it into an implementing abstract class.
So, what's the real advantage of a default method? (It looks more like a workaround than a new feature...)
UPDATE I understand that this approach is for backwards compatibility, but it still doesn't convince me so much. An interface represent a behaviour that a class MUST have. So a class implementing a certain interface has surely this behaviour. But if someone can arbitrarily change the interface, this constraint is broken. The behaviour can change anytime... Am I wrong?
This is for backwards compatibility.
If you have an interface that other people have implemented then if you add a new method to the interface all existing implementations are broken.
By adding a new method with a default implementation you remaining source-compatible with existing implementations.
For a slightly simple/contrived example that should hopefully demonstrate this let us say you created a library:
void drawSomething(Thing thing) {
}
interface Thing {
Color getColor();
Image getBackgroundImage();
}
Now you come to do a new version of your library and you want to add the concept of border colors, that's easy to add to the interface:
interface Thing {
Color getColor();
Color getBorderColor();
Image getBackgroundImage();
}
But the problem is that every single person using your library has to go back through every single Skin implementation they ever did and add this new method.
If instead you provided a default implementation to getBorderColor that just called getColor then everything "just works".
There have been a lot of methods acting on an abstract interface in the past. Before Java 8 they had to be put into an additional class pairing the interface, e.g. Collections with Collection.
This old approach was neither more convincing than default methods nor more practical. Instead of list.sort() you had to say Collections.sort(list). This also implies that you had to make a fundamental decision when creating an interface, either you require every List implementation to implement a sort method or you provide a sort method in a utility class that cannot be overridden.
With default methods you can have both, a standard implementation which the List implementations do not need to implement on its own but still can be overridden if a concrete implementation has a more efficient way to do it knowing its internals, e.g. ArrayList.sort passes its internal array directly to Arrays.sort skipping some intermediate operations.
Suppose at some point you want to add new functionality in declared interface, up to Java 7, If you will add a new method in declared an interface, you also have to define the implementation of the method in classes that are implementing that interface.
In java 8, You can add a default method containing the implementation and all the child class will inherit that method.
Edit : (After question update)
An interface represent a behaviour that a class MUST have
It still represent a behaviour that class must have, your confusion is how you are defining behaviour. All implementing class will inherit default method and are also free to write their own implementation. consider following two cases,
If implementing class does not provide own implementation and simply inherit default method. If you change behaviour of default method in interface, implementing classes will be having updated behaviour as they inherit default method so it holds An interface represent a behaviour that a class MUST have.
If implementing class provide own version of default method, and if you will change behaviour (only arguments) of default method. In this case implementing class will be having two overloaded methods, one which was earlier defined and second one is inherited default method. and if you change complete behaviour (arguments with return type also), It will create ambiguity in implementing class as you can not overload method by changing return type and Implementation will be broken. again it holds An interface represent a behaviour that a class MUST have.
Example :
Bulk data operation in collection is added in Java 8 (Reference : http://openjdk.java.net/jeps/107), to implement that forEach() method is added in Iterable interface. Adding abstract method in Iterable interface would break all the existing code because each class has to implement that method.
Solving the issue, following default forEach() method is added in Iterable interface,
interface Iterable
{
default void forEach(Consumer<? super T> action)
{
for (T t : this) action.accept(t);
}
}
Reference : Java 8 : Default method in Interface
I am looking for a java equivalent to the C# extension methods feature. Now I have been reading about Java 8's default methods, but as far as I can see, I can only add these to interfaces...
...is there any language feature that will allow me to write an extension method for a final class that doesn't implement an interface? (I'd rather not have to wrap it...)
Java doesn't have extension methods. Default methods are not extension methods. Let's look at each feature.
Default methods
Both Java and C# support this feature
Problems solved:
Many objects may implement the same interface and all of them may use the same implementation for a method. A base class could solve this issue but only if the interface implementors don't already have a base class as neither java nor C# support multiple inheritance.
An API would like to add a method to an interface without breaking the API consumers. Adding a method with a default implementation solves this.
Java's or C#'s default methods are a feature to add a default implementation to an interface. So objects that extend an interface don't have to implement the method, they could just use the default method.
interface IA { default public int AddOne(int i) { return i + 1; } }
Any object that implements IA doesn't have to implement AddOne because there is a default method that would be used.
public class MyClass implements IA { /* No AddOne implementation needed */ }
C# now has this feature in C# 8 (or .Net 5)
C#'s Extension Method
Problems solved:
Ability to add methods to sealed classes.
Ability to add methods to classes from third-party libraries without forcing inheritance.
Ability to add methods to model classes in environments where methods in model classes are not allowed for convention reasons.
The ability for IntelliSense to present these methods to you.
Example: The type string is a sealed class in C#. You cannot inherit from string as it is sealed. But you can add methods you can call from a string.
var a = "mystring";
a.MyExtensionMethed()
Java lacks this feature and would be greatly improved by adding this feature.
Conclusion
There is nothing even similar about Java's default methods and C#'s extension method features. They are completely different and solve completely different problems.
C# extension methods are static and use-site, whereas Java's default methods are virtual and declaration-site.
What I believe you are hoping for is the ability to "monkey-patch" a method into a class you do not control, but Java does not give you that (by design; it was considered and rejected.)
Another benefit of default methods over the C# approach is that they are reflectively discoverable, and in fact from the outside, don't look any different from "regular" interface methods.
One advantage of C#'s extension methods over Java's default methods is that with C#'s reified generics, extension methods are injected into types, not classes, so you can inject a sum() method into List<int>.
Above all, the main philosophical difference between Java's default methods and C#'s extension methods is that C# lets you inject methods into types you do not control (which is surely convenient for developers), whereas Java's extension methods are a first-class part of the API in which they appear (they are declared in the interface, they are reflectively discoverable, etc.) This reflects several design principles; library developers should be able to maintain control of their APIs, and library use should be transparent -- calling method x() on type Y should mean the same thing everywhere.
C# extension methods are just syntactic sugar for static methods that take the extended type as first argument. Java default methods are something completely different. To mimic C# extension methods, just write usual static methods. You will not have the syntatic sugar, however; Java does not have this feature.
Java default methods are real virtual methods. For example, they can be overridden. Consider a class X inheriting from an interface I that declares a default foo() method. If X or any of its super classes declares no own foo() method, then X will get the foo() implementation of I. Now, a subclass Y of X can override X.foo() like a usual method. Thus, default methods are not only syntactic sugar. They are real extensions of the method overriding and inheritance mechanism that cannot be mimicked by other language features.
Default methods even require special VM support, so they are not even a compiler only feature: During class loading, the hierarchy of a class has to be checked to determine which default methods it will inherit. Thus, this decision is made at runtime, not at compile time. The cool thing about it is that you do not have to recompile a class when an interface it inherits gets a new default method: The VM will, at class load time, assign that new method to it.
It is possible to have extension methods with some tricks.
You may give a try to Lombok or XTend. Although extension methods don't come with the out of the box Java implementation, both Lombok and XTend offers a fully working solution.
Lombok is a simple standalone code processing framework, which makes most of the criticized Java specific hassle less painful, including extension methods:
https://projectlombok.org/features/experimental/ExtensionMethod.html
Xtend http://www.eclipse.org/xtend/ goes a few lightyears forward, and implements a language which is a combination of the best parts of modern languages such as Scala on top of Java and Java type system. This allows implementing some classes in Xtend and others in Java within the same project. The Xtend code complies to valid Java code, so no JVM magic happens under the hood. On the other hand, it is a little too much if you have only extension methods missing.
JPropel https://github.com/nicholas22/jpropel-light implements LINQ style extension methods in Java using Lombok. It may worth of a peek :)