Now, we know that Java 8 has introduced default and static methods in interfaces.
Interfaces were originally introduced in Java to avoid the diamond problem that occurred in C++, in multiple inheritance.
But along with the introduction of default methods in interfaces in Java 8, now, Java has also introduced the diamond problem, which it avoided in previous versions.
Default methods are not compulsorily needed to be overridden.
But when a diamond problemoccurs using interfaces, the class implementing those interfaces must override the default methods.
So now, I have three questions in my mind:
Why is the need to have default methods?
Couldn't we have multiple inheritance through classes itself, in place of having default methods in interfaces?
And what was the need to avoid diamond problem in the previous versions, if they had to introduce it in Java 8 anyway?
Any good explanation or any link for explanation?
PS I did not find any link on the internet containing any good article on this.
All they said is that an abstract class gives you more concreteness.
As in, abstract classes can have constructors but interfaces cannot.
So again, I want to know, If abstract classes are more concrete, and can have constructors,
and anyways Java has introduced the diamond problem, why should we have interfaces now? Wouldn't abstract classes be good enough as a stand alone for multiple inheritance?
No, it didn't reintroduce the diamond problem, because interfaces still can't have any state, and default methods may not be final.
So, when you choose to implement two interfaces, you still have all the freedom you want to implement the default methods, either by choosing one of the provided default implementations, or by providing your own implementation. But you'll never have a problem of inheriting conflicting state from both interfaces, or inheriting two different final methods and not being able to resolve the conflict.
So, here are the answers to your questions:
To be able to introduce new methods in existing interfaces without breaking backward compatibility: existing implementations will automatically implement these methods since their implementation is in the base interface.
No, because that would introduce a diamond problem.
Irrelevant
Regarding Point 1:
In order to support lambda expression for all collection classes, like forEach method, it was necessary to add something which will have backward compatibility.
see this video for detail Lambda Peak Under the hood
Default methods make it possible to enhance an existing interface while providing binary compatibility with former versions of the interface to existing users.
See more here https://docs.oracle.com/javase/tutorial/java/IandI/nogrow.html
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.
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.
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
Is it a safe practice to use default methods as a poor's man version of traits in Java 8?
Some claim it may make pandas sad if you use them just for the sake of it, because it's cool, but that's not my intention. It is also often reminded that default methods were introduced to support API evolution and backward compatibility, which is true, but this does not make it wrong or twisted to use them as traits per se.
I have the following practical use case in mind:
public interface Loggable {
default Logger logger() {
return LoggerFactory.getLogger(this.getClass());
}
}
Or perhaps, define a PeriodTrait:
public interface PeriodeTrait {
Date getStartDate();
Date getEndDate();
default isValid(Date atDate) {
...
}
}
Admitedly, composition could be used (or even helper classes) but it seems more verbose and cluttered and does not allow to benefit from polymorphism.
So, is it ok/safe to use default methods as basic traits, or should I be worried about unforeseen side effects?
Several questions on SO are related to Java vs Scala traits; that's not the point here. I'm not asking merely for opinions either. Instead, I'm looking for an authoritative answer or at least field insight: if you've used default methods as traits on your corporate project, did it turn out to be a timebomb?
The short answer is: it's safe if you use them safely :)
The snarky answer: tell me what you mean by traits, and maybe I'll give you a better answer :)
In all seriousness, the term "trait" is not well-defined. Many Java developers are most familiar with traits as they are expressed in Scala, but Scala is far from the first language to have traits, either in name or in effect.
For example, in Scala, traits are stateful (can have var variables); in Fortress they are pure behavior. Java's interfaces with default methods are stateless; does this mean they are not traits? (Hint: that was a trick question.)
Again, in Scala, traits are composed through linearization; if class A extends traits X and Y, then the order in which X and Y are mixed in determines how conflicts between X and Y are resolved. In Java, this linearization mechanism is not present (it was rejected, in part, because it was too "un-Java-like".)
The proximate reason for adding default methods to interfaces was to support interface evolution, but we were well aware that we were going beyond that. Whether you consider that to be "interface evolution++" or "traits--" is a matter of personal interpretation. So, to answer your question about safety ... so long as you stick to what the mechanism actually supports, rather than trying to wishfully stretch it to something it does not support, you should be fine.
A key design goal was that, from the perspective of the client of an interface, default methods should be indistinguishable from "regular" interface methods. The default-ness of a method, therefore, is only interesting to the designer and implementor of the interface.
Here are some use cases that are well within the design goals:
Interface evolution. Here, we are adding a new method to an existing interface, which has a sensible default implementation in terms of existing methods on that interface. An example would be adding the forEach method to Collection, where the default implementation is written in terms of the iterator() method.
"Optional" methods. Here, the designer of an interface is saying "Implementors need not implement this method if they are willing to live with the limitations in functionality that entails". For example, Iterator.remove was given a default which throws UnsupportedOperationException; since the vast majority of implementations of Iterator have this behavior anyway, the default makes this method essentially optional. (If the behavior from AbstractCollection were expressed as defaults on Collection, we might do the same for the mutative methods.)
Convenience methods. These are methods that are strictly for convenience, again generally implemented in terms of non-default methods on the class. The logger() method in your first example is a reasonable illustration of this.
Combinators. These are compositional methods that instantiate new instances of the interface based on the current instance. For example, the methods Predicate.and() or Comparator.thenComparing() are examples of combinators.
If you provide a default implementation, you should also provide some specification for the default (in the JDK, we use the #implSpec javadoc tag for this) to aid implementors in understanding whether they want to override the method or not. Some defaults, like convenience methods and combinators, are almost never overridden; others, like optional methods, are often overridden. You need to provide enough specification (not just documentation) about what the default promises to do, so the implementor can make a sensible decision about whether they need to override it.