As a rule, in the context of a large project, is it considered safe to take make an existing, ubiquitously used interface into a functional interface?
E.g., given an existing interface and class:
public interface Interface {
public double calculateSomething(double x);
public void doSomething();
}
which is implemented by
class InterfaceImplementer implements Interface {
public double calculateSomething(double x) {
return 2 * x;
}
public void doSomething() {
// insert specific behavior here
}
}
can I safely change the interface by defining all but one method as default:
public interface Interface {
public double calculateSomething(double x);
default void doSomething() {
// insert some default behavior here
}
}
So that I can go from defining an object as
Interface object = new InterfaceImplementer() {
#Override
public double calculateSomething(double x) {
return 2 * x;
}
};
to
Interface object = (x) -> 2 * x;
while still being able to define objects in the old, tedious way.
From what I can tell, this runs no risk of upsetting any existing code, and I've made such a change to a large project and had no runtime or compile errors. But I want some confirmation whether this matches up with common knowledge and best practices.
Any interface that only has a single non-default method (only one method needs to be implemented in a class) is by definition a functional interface. This is a good rule!
However, a #FunctionalInterface annotation has the advantage of enforcing the "only one method in the interface for a functional interface"-rule. So if you added it to your original two-method interface, you would have gotten a compiler error. Therefore by explicitly adding #FunctionalInterface you declare your intent and make your code more clear to future maintainers.
On java code level, I can think of one problem: since this interface already had contained 2 methods at some point in the past, you may want to add another method to it later on. You won't be able to add another method to a functional interface, since it has to remain a functional interface so you can use it as a functional interface. You will have to create an interface that inherits from this one. Which leads me to the main point.
It may have been logical to have those 2 methods in one interface before, but is it really logical now? Refactor the code, separate the interfaces; either make one extend another or use an interface that inherits from both, your call. If the interface is to be used as a functional one, make it functional. It will be clean. It will be understandable. You will be able to add methods to one of those interfaces in the future without further refactoring.
The Java API states:
However, the compiler will treat any interface meeting the definition of a functional interface as a functional interface regardless of whether or not a FunctionalInterface annotation is present on the interface declaration.
Therefore there is no risk to add that annotation.
Well, it's not the #Functional that might break anything, but adding a default implementation may lead to compilation errors for abstract classes that implement or interfaces that extend multiple interfaces declaring methods with override-equivalent signatures:
The following compiles fine:
interface I {
void a();
}
interface J {
void a();
}
interface K extends I, J {}
while this doesn't:
interface I {
default void a() {}
}
interface J {
void a();
}
interface K extends I, J {}
The default method a() inherited from I conflicts with another method inherited from J
So if you do this in a library, code using this may fail to compile after the change.
Related
An interface in Java is similar to a class, but the body of an
interface can include only abstract methods and final fields
(constants).
Recently, I saw a question, which looks like this
interface AnInterface {
public default void myMethod() {
System.out.println("D");
}
}
According to the interface definition, only abstract methods are allowed. Why does it allow me to compile the above code? What is the default keyword?
On the other hand, when I was trying to write below code, then it says modifier default not allowed here
default class MyClass{
}
instead of
class MyClass {
}
Can anyone tell me the purpose of the default keyword? Is it only allowed inside an interface? How does it differ from default (no access modifier)?
It's a new feature in Java 8 which allows an interface to provide an implementation. Described in Java 8 JLS-13.5.6. Interface Method Declarations which reads (in part)
Adding a default method, or changing a method from abstract to default, does not break compatibility with pre-existing binaries, but may cause an IncompatibleClassChangeError if a pre-existing binary attempts to invoke the method. This error occurs if the qualifying type, T, is a subtype of two interfaces, I and J, where both I and J declare a default method with the same signature and result, and neither I nor J is a subinterface of the other.
What's New in JDK 8 says (in part)
Default methods enable new functionality to be added to the interfaces of libraries and ensure binary compatibility with code written for older versions of those interfaces.
Default methods were added to Java 8 primarily to support lambda expressions. The designers (cleverly, in my view) decided to make lambdas syntax for creating anonymous implementations of an interface. But given lambdas can only implement a single method they would be limited to interfaces with a single method which would be a pretty severe restriction. Instead, default methods were added to allow more complex interfaces to be used.
If you need some convincing of the claim that default was introduced due to lambdas, note that the straw man proposal of Project Lambda, by Mark Reinhold, in 2009, mentions 'Extension methods' as a mandatory feature to be added to support lambdas.
Here's an example demonstrating the concept:
interface Operator {
int operate(int n);
default int inverse(int n) {
return -operate(n);
}
}
public int applyInverse(int n, Operator operator) {
return operator.inverse(n);
}
applyInverse(3, n -> n * n + 7);
Very contrived I realise but should illustrate how default supports lambdas. Because inverse is a default it can easily be overriden by a implementing class if required.
A new concept is introduced in Java 8 called default methods. Default methods are those methods which have some default implementation and helps in evolving the interfaces without breaking the existing code. Lets look at an example:
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");
}
}
class SimpleInterfaceImpl implements SimpleInterface {
#Override
public void doSomeWork() {
System.out.println("Do Some Work implementation in the class");
}
/*
* Not required to override to provide an implementation
* for doSomeOtherWork.
*/
public static void main(String[] args) {
SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
simpObj.doSomeWork();
simpObj.doSomeOtherWork();
}
}
and the output is:
Do Some Work implementation in the class
DoSomeOtherWork implementation in the interface
Something that was overlooked in the other answers was its role in annotations. As far back as Java 1.5, the default keyword came about as a means to provide a default value for an annotation field.
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface Processor {
String value() default "AMD";
}
It usage was overloaded with the introduction of Java 8 to allow one to define a default method in interfaces.
Something else that was overlooked: the reason that the declaration default class MyClass {} is invalid is due to the way that classes are declared at all. There's no provision in the language that allows for that keyword to appear there. It does appear for interface method declarations, though.
Default methods in an interface allow us to add new functionality without breaking old code.
Before Java 8, if a new method was added to an interface, then all the implementation classes of that interface were bound to override that new method, even if they did not use the new functionality.
With Java 8, we can add the default implementation for the new method by using the default keyword before the method implementation.
Even with anonymous classes or functional interfaces, if we see that some code is reusable and we don’t want to define the same logic everywhere in the code, we can write default implementations of those and reuse them.
Example
public interface YourInterface {
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");
}
}
class SimpleInterfaceImpl implements YourInterface{
/*
* Not required to override to provide an implementation
* for doSomeOtherWork.
*/
#Override
public void doSomeWork() {
System.out.println("Do Some Work implementation in the class");
}
/*
* Main method
*/
public static void main(String[] args) {
SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
simpObj.doSomeWork();
simpObj.doSomeOtherWork();
}
}
The new Java 8 feature (Default Methods) allows an interface to provide an implementation when its labeled with the default keyword.
For Example:
interface Test {
default double getAvg(int avg) {
return avg;
}
}
class Tester implements Test{
//compiles just fine
}
Interface Test uses the default keyword which allows the interface to provide a default implementation of the method without the need for implementing those methods in the classes that uses the interface.
Backward compatibility:
Imagine that your interface is implemented by hundreds of classes, modifying that interface will force all the users to implement the newly added method, even though its not essential for many other classes that implements your interface.
Facts & Restrictions:
1-May only be declared within an interface and not within a class or
abstract class.
2-Must provide a body
3-It is not assumed to be public or abstract as other normal methods used in an interface.
A very good explanation is found in The Java™ Tutorials, part of the explanation is as follows:
Consider an example that involves manufacturers of computer-controlled cars who publish industry-standard interfaces that describe which methods can be invoked to operate their cars. What if those computer-controlled car manufacturers add new functionality, such as flight, to their cars? These manufacturers would need to specify new methods to enable other companies (such as electronic guidance instrument manufacturers) to adapt their software to flying cars. Where would these car manufacturers declare these new flight-related methods? If they add them to their original interfaces, then programmers who have implemented those interfaces would have to rewrite their implementations. If they add them as static methods, then programmers would regard them as utility methods, not as essential, core methods.
Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.
Default methods enable you to add new functionality to the interfaces of your apps. It can also be used to have a multi inheritance.
In addition to default methods, you can define static methods in interfaces. This makes it easier for you to organize helper methods
I am not asking this -> Why is there no multiple inheritance in Java, but implementing multiple interfaces is allowed?
In Java, multiple inheritance isn't allowed, but, after Java 8, Interfaces can have default methods (can implement methods itself), just like abstract classes. Within this context, it multiple inheritance should also be allowed.
interface TestInterface
{
// abstract method
public void square(int a);
// default method
default void show()
{
System.out.println("Default Method Executed");
}
}
Things are not so simple.
If a class implements multiple interfaces that defines default methods with the same signature the compiler will force you to override this method for the class.
For example with these two interfaces :
public interface Foo {
default void doThat() {
// ...
}
}
public interface Bar {
default void doThat() {
// ...
}
}
It will not compile :
public class FooBar implements Foo, Bar{
}
You should define/override the method to remove the ambiguity.
You could for example delegate to the Bar implementation such as :
public class FooBar implements Foo, Bar{
#Override
public void doThat() {
Bar.super.doThat();
}
}
or delegate to the Foo implementation such as : :
public class FooBar implements Foo, Bar {
#Override
public void doThat() {
Foo.super.doThat();
}
}
or still define another behavior :
public class FooBar implements Foo, Bar {
#Override
public void doThat() {
// ...
}
}
That constraint shows that Java doesn't allow multiple inheritancy even for interface default methods.
I think that we cannot apply the same logic for multiple inheritances because multiples issues could occur which the main are :
overriding/removing the ambiguity for a method in both inherited classes could introduce side effects and change the overall behavior of the inherited classes if they rely on this method internally. With default interfaces this risk is also around but it should be much less rare since default methods are not designed to introduce complex processings such as multiple internal invocations inside the class or to be stateful (indeed interfaces cannot host instance field).
how to inherit multiple fields ? And even if the language allowed it you would have exactly the same issue as this previously quoted : side effect in the behavior of the inherited class : a int foo field defined in a A and B class that you want to subclass doesn't have the same meaning and intention.
The language designers already thought about that, so these things are enforced by the compiler. So if you define:
interface First {
default void go() {
}
}
interface Second {
default void go() {
}
}
And you implement a class for both interfaces:
static class Impl implements First, Second {
}
you will get a compilation error; and you would need to override go to not create the ambiguity around it.
But you could be thinking that you can trick the compiler here, by doing:
interface First {
public default void go() {
}
}
static abstract class Second {
abstract void go();
}
static class Impl extends Second implements First {
}
You could think that First::go already provides an implementation for Second::go and it should be fine. This is too taken care of, thus this does not compile either.
JLS 9.4.1.3 : Similarly, when an abstract and a default method with matching signatures are inherited, we produce an error. In this case, it would be possible to give priority to one or the other - perhaps we would assume that the default method provides a reasonable implementation for the abstract method, too. But this is risky, since other than the coincidental name and signature, we have no reason to believe that the default method behaves consistently with the abstract method's contract - the default method may not have even existed when the subinterface was originally developed. It is safer in this situation to ask the user to actively assert that the default implementation is appropriate (via an overriding declaration).
The last point I would bring in, to solidify that multiple inheritance is not allowed even with new additions in java, is that static methods from interfaces are not inherited. static methods are inherited by default:
static class Bug {
static void printIt() {
System.out.println("Bug...");
}
}
static class Spectre extends Bug {
static void test() {
printIt(); // this will work just fine
}
}
But if we change that for an interface (and you can implement multiple interfaces, unlike classes):
interface Bug {
static void printIt() {
System.out.println("Bug...");
}
}
static class Spectre implements Bug {
static void test() {
printIt(); // this will not compile
}
}
Now, this is prohibited by the compiler and JLS too:
JLS 8.4.8 : A class does not inherit static methods from its superinterfaces.
Java doesn't allow multiple inheritance for fields. This would be difficult to support in the JVM as you can only have references to the start of an object where the header is, not arbitrary memory locations.
In Oracle/Openjdk, objects have a header followed by the fields of the most super class, then the next most super class, etc. It would be a significant change to allow the fields of a class to appear at different offsets relative to the header of an object for different subclasses. Most likely object references would have to become a reference to the object header and a reference to the fields to support this.
default methods in interfaces pose a problem that :
If both of the implemented interfaces define a default method with
same method signature, then the implementation class does not know
which default method to use.
The implementation class should define explicitly specify which default method to use or define it's own one.
Thus default methods in Java-8 do not facilitate multiple inheritance. The main motivation behind default methods is that if at some point we need to add a method to an existing interface, we can add a method without changing the existing implementation classes. In this way, the interface is still compatible with older versions. However, we should remember the motivation of using Default Methods and should keep the separation of interface and implementation.
The main issues with multiple inheritance are ordering (for overriding and calls to super), fields and constructors; interfaces don't have fields or constructors, so they don't cause problems.
If you look at other languages they usually fall in two broad categories:
Languages with multiple inheritance plus a few features to disambiguate special cases: virtual inheritance [C++], direct calls to all superconstructors in the most-derived class [C++], linearization of superclasses [Python], complex rules for super [Python], etc.
Languages with a differente concept, usually called interfaces, traits, mixins, modules, etc. that impose some limitations such as: no constructors [Java] or no constructors with parameters [Scala until very recently], no mutable fields [Java], specific rules for overriding (e.g. mixins take precedence over base classes [Ruby] so you can include them when you need a bunch of utility methods), etc. Java has become a language like these.
Why just by disallowing fields and constructors you solve many issues related to multiple inheritance?
You can't have duplicated fields in duplicated base classes.
The main class hierarchy is still linear.
You can't construct your base objects the wrong way.
Imagine if Object had public/protected fields and all subclasses had constructors setting those fields. When you inherit from more than one class (all of them derived from Object), which one gets to set the fields? The last class? They become siblings in the hierarchy, so they know nothing about each other. Should you have multiple copies of Object to avoid this? Would all classes interoperate correctly?
Remember that fields in Java are not virtual (overridable), they are simply data storage.
You could make a language where fields behave like methods and could be overridden (the actual storage would be always private), but that would be a much bigger change and problably wouldn't be called Java anymore.
Interfaces can't be instantiated by themselves.
You should always combine them with a concrete class. That eliminates the need for constructors and makes the programmer's intent clearer too (that is, what is meant to be a concrete class and what's an accessory interface/mixin). This also provides a well-defined place to solve all ambiguities: the concrete class.
That is mostly related to "diamonds problem" i think. Right now if you implement multiple interfaces with the same method, compiler forces you to override method the one you want to implement, because it don't know which on to use. I guess Java creators wanted to remove this problem back when interfaces couldn't use default methods. Now they came up with idea, that is good to be able to have methods with implementation in interfaces, as you can still use those as functional interfaces in streams / lambda expressions and utilize their default methods in processing. You cannot do that with classes but diamond problem still exist there. That is my guess :)
class A{
void m1(){
System.out.println("m1-A");
}
}
class B{
void m1(){
System.out.println("m1-B");
}
}
class C extends A, B{ // this will give an error
// inheritance means making all variables and/or methods available to the child class, here child class will get confused as which m1() method to inherit, hence an error
}
JAVA DOES SUPPORT MULTIPLE INHERITANCE.
If you make a OVERALL COMPARISON OF THE PROGRAMMING LANGUAGE,JAVA,THEN YOU COME TO KNOW THAT I AM TRUE.
Java's topclass or the root class in the Ancestor Hierarchy is the Object class.
This class is a Superclass of all other classes. Hence, each class in Java that we declare or is predefined in the API itself inherits this Object class.
Moreover, Java provides us to inherit one more class of our choice.
Hence, we can say that we are performing INTERLOCKED BUT MULTIPLE INHERITANCE.
2ND Way
Java supports Multiple Inheritance of Interfaces. So you can use as many interface implementations you want. But note, implementing an interface does not define IS A relationship as in case of Inheritance of Classes is possible.
I'm looking for a solution, that allows to protect the default methods from inheritance. The easiest solution could be - extend from class and etc... but in my case it's not possible.
Can someone suggest how to solve this problem? Could there be any workarounds?
Atm I have following code, which needs to be reworked (if/any possible):
public interface MyInterface1 {
default boolean isA(Object obj) {
return (boolean) obj.equals("A") ? true : false;
}
default boolean isB(Object obj) {
return (boolean) obj.equals("B") ? true : false;
}
}
public class MyClass extends MyLogic implements MyInterface, MyInterface1 {
// this class allows to inherit methods from both interfaces,
// but from my perspective i'd like to use the methods from MyInterface1 as it is,
// with a 'protection' from inheritance. is that possible?
}
You seem to want a way to write your interface so that implementing classes cannot provide their own implementations of its default methods. There is no way to do this, and indeed it runs counter to the purpose of interfaces in general and default members in particular.
The point of default methods is to provide a way to add methods to existing interfaces without instantly breaking all their existing implementations. Generally speaking, this is a binary compatibility issue, not a functionality issue. There's no particular reason to suppose in general that default implementations can provide the intended functionality, but without them, even old code that doesn't rely on the new methods at all is incompatible with interface revisions that add methods.
I think you have a factoring issue. Rather than trying to force classes to provide a specific implementation of a specific method -- which cannot even refer to that class's members, except possibly others defined by the same interface -- you should provide the common methods in a class of their own. After all, since you want all classes involved to provide identical implementations, it doesn't matter which class's implementations you actually use. Moreover, there is therefore no particular usefulness in marking any given class as providing implementations of the well-known methods.
Example:
public class MyImplementation1 {
public static boolean isA(Object obj) {
return obj.equals("A");
}
public static isB(Object obj) {
return obj.equals("B");
}
}
// Wherever needed, use as MyImplementation1.isA(o), etc.
You can do this even if you want these pre-baked implementations to operate in terms of the other methods of your interface. In that case, just add an argument to the fixed methods that provides the object to operate on. Perhaps that's what the obj arguments in your example were supposed to be; in that case, this may be closer to what you're after:
public interface MyInterface3 {
public String someInterfaceMethod();
}
public class MyImplementation2 {
public static boolean isA(MyInterface3 subject) {
return subject.someInterfaceMethod().equals("A");
}
public static boolean isB(MyInterface3 subject) {
return subject.someInterfaceMethod().equals("B");
}
}
You can't. At least if you restrict yourself to a pure-java-compiler solution.
And the reason is because it was not designed to do that: the purpose is to add new methods to existing interface (like java.util.Collection) without breaking the implementations. That way, we have sort(), stream(), forEach() on Collection.
If you were to allow such thing (forbidding implementation), then it would means a change in the interface would result in a compilation error for implementation (because they would override the method, method that would been rendered final). That was not the purpose.
There are several other options to achieve that, depending on your need:
Abstract class with final method being the previously default method.
Testing the default behavior using unit testing.
Testing the possible implementation and check they don't override it.
The last case can probably be done easily with Reflections: you would have to list all implementations, and check for each interface's default method that there is no overriding using Reflections.
I take it you mean you want to write a class that uses the default methods of an interface, but does not inherit them.
In your example code, you attempted to use the default methods by implementing the interface. When you implement an interface, by design you also inherit all its methods. This is the Liskov Substitution Principle. By implementing the interface you are telling your users that all instances of your class are substitutable for instances of the interface. But if the interface default methods weren't inherited, this wouldn't be true, so you would be lying to users of your class.
To have your class use the interface's default methods without inheriting them, don't implement the interface! Instead, use a helper class that does:
public interface MyInterface1 {
default boolean isA(Object obj) {
return obj.equals("A"); // or "A".equals(obj) to avoid NullPointerException
}
default boolean isB(Object obj) {
return obj.equals("B");
}
}
public class MyClass extends MyLogic implements MyInterface {
private static class Helper implements MyInterface1 {
void doSomeWork() {
// do something that calls isA() and isB()...
}
}
public void someMethodOfMyClass() {
// ...
Helper.doSomeWork();
// ...
}
}
No, This is not possible due to the way java implements the interface (pun intended). For more information as to the reason for this, see the answers to this question Why is "final" not allowed in Java 8 interface methods?
However here are some other ways to guide a developer not to override a default method:
A source code comment
//Do not inherit please
A javadoc comment
An interface in Java is similar to a class, but the body of an
interface can include only abstract methods and final fields
(constants).
Recently, I saw a question, which looks like this
interface AnInterface {
public default void myMethod() {
System.out.println("D");
}
}
According to the interface definition, only abstract methods are allowed. Why does it allow me to compile the above code? What is the default keyword?
On the other hand, when I was trying to write below code, then it says modifier default not allowed here
default class MyClass{
}
instead of
class MyClass {
}
Can anyone tell me the purpose of the default keyword? Is it only allowed inside an interface? How does it differ from default (no access modifier)?
It's a new feature in Java 8 which allows an interface to provide an implementation. Described in Java 8 JLS-13.5.6. Interface Method Declarations which reads (in part)
Adding a default method, or changing a method from abstract to default, does not break compatibility with pre-existing binaries, but may cause an IncompatibleClassChangeError if a pre-existing binary attempts to invoke the method. This error occurs if the qualifying type, T, is a subtype of two interfaces, I and J, where both I and J declare a default method with the same signature and result, and neither I nor J is a subinterface of the other.
What's New in JDK 8 says (in part)
Default methods enable new functionality to be added to the interfaces of libraries and ensure binary compatibility with code written for older versions of those interfaces.
Default methods were added to Java 8 primarily to support lambda expressions. The designers (cleverly, in my view) decided to make lambdas syntax for creating anonymous implementations of an interface. But given lambdas can only implement a single method they would be limited to interfaces with a single method which would be a pretty severe restriction. Instead, default methods were added to allow more complex interfaces to be used.
If you need some convincing of the claim that default was introduced due to lambdas, note that the straw man proposal of Project Lambda, by Mark Reinhold, in 2009, mentions 'Extension methods' as a mandatory feature to be added to support lambdas.
Here's an example demonstrating the concept:
interface Operator {
int operate(int n);
default int inverse(int n) {
return -operate(n);
}
}
public int applyInverse(int n, Operator operator) {
return operator.inverse(n);
}
applyInverse(3, n -> n * n + 7);
Very contrived I realise but should illustrate how default supports lambdas. Because inverse is a default it can easily be overriden by a implementing class if required.
A new concept is introduced in Java 8 called default methods. Default methods are those methods which have some default implementation and helps in evolving the interfaces without breaking the existing code. Lets look at an example:
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");
}
}
class SimpleInterfaceImpl implements SimpleInterface {
#Override
public void doSomeWork() {
System.out.println("Do Some Work implementation in the class");
}
/*
* Not required to override to provide an implementation
* for doSomeOtherWork.
*/
public static void main(String[] args) {
SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
simpObj.doSomeWork();
simpObj.doSomeOtherWork();
}
}
and the output is:
Do Some Work implementation in the class
DoSomeOtherWork implementation in the interface
Something that was overlooked in the other answers was its role in annotations. As far back as Java 1.5, the default keyword came about as a means to provide a default value for an annotation field.
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface Processor {
String value() default "AMD";
}
It usage was overloaded with the introduction of Java 8 to allow one to define a default method in interfaces.
Something else that was overlooked: the reason that the declaration default class MyClass {} is invalid is due to the way that classes are declared at all. There's no provision in the language that allows for that keyword to appear there. It does appear for interface method declarations, though.
Default methods in an interface allow us to add new functionality without breaking old code.
Before Java 8, if a new method was added to an interface, then all the implementation classes of that interface were bound to override that new method, even if they did not use the new functionality.
With Java 8, we can add the default implementation for the new method by using the default keyword before the method implementation.
Even with anonymous classes or functional interfaces, if we see that some code is reusable and we don’t want to define the same logic everywhere in the code, we can write default implementations of those and reuse them.
Example
public interface YourInterface {
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");
}
}
class SimpleInterfaceImpl implements YourInterface{
/*
* Not required to override to provide an implementation
* for doSomeOtherWork.
*/
#Override
public void doSomeWork() {
System.out.println("Do Some Work implementation in the class");
}
/*
* Main method
*/
public static void main(String[] args) {
SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
simpObj.doSomeWork();
simpObj.doSomeOtherWork();
}
}
The new Java 8 feature (Default Methods) allows an interface to provide an implementation when its labeled with the default keyword.
For Example:
interface Test {
default double getAvg(int avg) {
return avg;
}
}
class Tester implements Test{
//compiles just fine
}
Interface Test uses the default keyword which allows the interface to provide a default implementation of the method without the need for implementing those methods in the classes that uses the interface.
Backward compatibility:
Imagine that your interface is implemented by hundreds of classes, modifying that interface will force all the users to implement the newly added method, even though its not essential for many other classes that implements your interface.
Facts & Restrictions:
1-May only be declared within an interface and not within a class or
abstract class.
2-Must provide a body
3-It is not assumed to be public or abstract as other normal methods used in an interface.
A very good explanation is found in The Java™ Tutorials, part of the explanation is as follows:
Consider an example that involves manufacturers of computer-controlled cars who publish industry-standard interfaces that describe which methods can be invoked to operate their cars. What if those computer-controlled car manufacturers add new functionality, such as flight, to their cars? These manufacturers would need to specify new methods to enable other companies (such as electronic guidance instrument manufacturers) to adapt their software to flying cars. Where would these car manufacturers declare these new flight-related methods? If they add them to their original interfaces, then programmers who have implemented those interfaces would have to rewrite their implementations. If they add them as static methods, then programmers would regard them as utility methods, not as essential, core methods.
Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.
Default methods enable you to add new functionality to the interfaces of your apps. It can also be used to have a multi inheritance.
In addition to default methods, you can define static methods in interfaces. This makes it easier for you to organize helper methods
I want to create a class that does not implement any method of an interface, but extends any implementation of A with it's own methods.
Let's assume we have the following:
public interface A {
public void a();
}
and
public class B implements A {
#override
public void a() {
System.out.println("a");
}
}
I now want to create a class C that also implements A and takes another random implementation of A:
public class C implements A {
public C(A a) {
//what do I need to do with a here?
}
public void c() {
System.out.println("c");
}
}
Now if I have the following:
A b = new B();
A c = new C(b);
c.a();
The output should be "a".
I can't just
public class C extends B {
...
as C is supposed to be able to work with any implementation of A, not just B.
I also can't
public class C implements A {
private a;
public C(A a) {
this.a = a;
}
#override
public void a() {
a.a();
}
public void c() {
System.out.println("c");
}
}
since that would mean that I have to redirect every single interface method and rewrite C whenever something changes with A.
Is there any way to handle that problem in Java?
For another example, replace A: List; B: ArrayList; C: FooList; a(): size()
What you're looking for is a dynamic proxy, which automatically implements all the methods of an interface by delegating to a concrete implementation of this interface. That's not trivial, but not so complex to do either, using Java's Proxy class.
A concrete example of such a proxy, which "adds" methods to any instance of PreparedStatement by wrapping it, can be found at https://github.com/Ninja-Squad/ninja-core/blob/master/src/main/java/com/ninja_squad/core/jdbc/PreparedStatements.java
Unfortunately, there's no way to do it in Java, other than your last code snippet. Various IDEs will help you with the code generation, though, and marking all methods #override will mean that you'll get a warning or an error if your implementation of C doesn't exactly match A's interface.
For Eclipse (and, apparently, IntelliJ), see the "Generate Delegate Methods" command.
This is probably not going to immediately help you, but if you used Java 8, you could solve this with defender methods, which are methods implemented in the interface.
You would then, for each existing implementation class, add your own class which extends the class and implements your additional interface with the defender methods. The methods would be "mixed into" your class.
Java 8 is just around the corner, though, so it is not a far-off solution. Oracle has promised it will release it by the end of this quarter, meaning in less than a month and a half at the latest.
Is there any way to handle that problem in Java?
Basically, no.
What you are describing a wrapper class that delegates calls to the wrapped method. The only way you can implement that (in regular Java) is to implement all of the methods and have them make the calls.
Another alternative would be to use the Proxy class ... which will effectively generate a dynamic proxy. The problem is that this requires an InvocationHandler that will (I guess) use reflection to make the call to the wrapped object. It is complicated and won't be efficient.
If your goal is simply to avoid writing code, I think this is a bad idea. If your goal is to writing the same code over and over (e.g. because you have lots of exampled of C for a given A), then consider coding an abstract class for the C classes that deals with the wrappering / delegation.
It would also be possible to generate the wrapper class C from nothing, using the BCEL library or similar. But that's an even worse idea (IMO).