For a while I have been puzzled as to why we need default methods in Interfaces, and today I was reading about it. Even though few of my questions are answered, I still have a few queries.
Let's take a simple example, I've an interface1. Class A and class B implement interface1. interface1 has a method X.
interface interface1{
void methodX();
}
class A implements interface1{
#override
public void methodX(){
//something
};
}
class B implements interface1{
#override
public void methodX(){
//something
};
}
From what I understood, since adding a new method Y to interface1, would have broken Class A and class B, default methods were introduced. This means that now I can add a default method, without the need for modifying Class A and Class B. This also means that the default method has to be generic enough to do whatever we expect it to do, for both class A and class B.
Now, let's consider that we normally add functions in interface so that we can provide a class specific implementation to them by overriding it. So basically, if I am adding a method Y in an interface as default, then I will expect class A and class B (or class A/ClassB) to override the method.
Which means, I will be modifying Class A/Class B or both.
This is what confuses me. This could have been handled by creating a new interface and modifying 1 (or both) class(es) to implement that new interface (interface 2 extending interface1), and then provide implementation for the same in the class.
interface interface2 extends interface1{
void methodY();
}
class A implements interface2{
#override
public void methodY(){
//something
}
}
class B implements interface1{
#override
public void methodX(){
//something
};
}
How does default method, actually help us in not modifying the classes which implements it.
Default methods provides "base" implementation of some behaviour which can be composed of existing methods at given interface. For example, you have an interface with add method. This is enough to provide default implementation for addAll behaviour:
default void addAll(Collection<? extends E> c) { for (E e : c) { add(e); } }
Another example can be sort method in List, which can be implemented by provided methods: get(int), set(int,E), size(). Subclass might override this default implementation in order to provide more efficient sorting based on specific list properties. In LinkedList you can take advantage of attaching/detaching nodes (no need to shift an elements on right when inserting or removing node), in ArrayList you can take advantage of super fast access of element at any index).
If you mandate all the implementing classes to override the new method, then it should (if there is no valid default implementation) not be a default method.
But, the approach you have said in which to create a new interface that extends the existing one and making the classes that wish to override the new method(s) by changing the interface type they implement will be problematic since the new method is part of the new interface, you cannot access it when you have the parent/base interface type.
Example:
Existing code:
interface Base {
void m1();
}
class A implements Base {
#Override
public void m1() {
....
}
}
class B implements Base {
#Override
public void m1() {
....
}
}
You create the following interface
interface ExtendedBase extends Base {
void m2();
}
Only class A wants to implement m2. So, it becomes
class A implements ExtendedBase {
#Override
public void m1() {
....
}
#Override
public void m2() {
....
}
}
All is good so far.
When you have a method that takes an object of type Base, you can only call m1 on it (irrespective of you pass object of type A or B)
void someMethod(Base base) {
base.m1();
//base.m2(); won't work
}
To actually make use of m2 elsewhere, you need to change Base to ExtendedBase which would mean that you can no longer pass a B to it. So, you have made all classes implement m2 anyway.
Since a default method is defined in an interface, it can only access instance methods also defined in the same interface. Hence, it can only invoke functionality that is actually provided by the implementing classes (in your example A and B).
The default method does not "change" the classes' behavior, it extends it by accessing existing, properly defined behavior.
So basically, if I am adding a method Y in an interface as default, then I will expect class A and class B (or class A/ClassB) to override the method.
This wrong.
The idea of default method is to introduce new method without break compatibility with old code.
Existing implementation classes do not need to be modified to work with new default method.
This could have been handled by creating a new interface and modifying 1 (or both) class(es) to implement that new interface (interface 2 extending interface1), and then provide implementation for the same in the class.
Then you have to touch / modify the implementation class. That's what default method try to avoid.
Related
Suppose I have an interface defined as:
public interface TestInterface1 {
public void add();
}
which is implemented by classes A, B and C.
Now I need to add a subtract functionality only to class C; for that I have created a new interface TestInterface2 and implemented that to class C:
public interface TestInterface2 {
public void sub();
}
Class C looks like this:
public class C implements TestInterface1, TestInterface2 {
public void add() {
System.out.println("I am in add");
}
public void sub() {
System.out.println("I am in Sub");
}
}
Now the problem is instances of C has been use in hundreds of places like this:
TestInterface1 c = new C();
And only class C is getting the add method of TestInterface1.
Is there any way or pattern to implement both the interfaces in class C so that where ever the object of class C is created, it gets both the method from TestInterface1 and TestInterface2?
If you can change your interfaces then make TestInterface1 extend the other one, so object created using first interface can use its parent methods.
public interface TestInterface1 extends TestInterface2{
public void add();
}
Before we get into this, you have to consider why you're even using interfaces for this at all. An interface guarantees that all instances are using the same implementations. If you want a specific class to have a more specific implementation, then that sounds more like a method on the concrete class more than it does a new interface at all.
Regardless, we can discuss your options. One of them is cleaner and conveys clear intent; the other muddies things.
The first option - which conveys clearer intent - is to eschew the usage of the more restrictive interface and instead use TestInterface2 for every declaration that you want to use C.
This means you'd write TestInterface2 c = new C(); everywhere you wanted to use it. Yes, you'd be changing it in all of the places that you're using C, but given that you have to have a method specifically attached to instances of C, this option is clearest.
This would be the same approach if you just wrote the method in C. There's really no difference between the two and I personally would prefer if you wrote the method that only belonged to C in C.
The second option - which muddies things and also requires Java 8 - is to use a default method. This requires that you implement it in the interface at first...
public interface TestInterface {
default void sub() {
System.out.println("I am in sub!");
}
}
...but you can override it in your class later. This muddies things because any class that implements TestInterface has access to this default method, which is likely not what you want for your requirements.
In the Collection Interface I found a method named removeIf() that contains its implementation.
default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
I want to know if there is any way to define method body in an interface?
What is the default keyword and how does it work?
From https://dzone.com/articles/interface-default-methods-java
Java 8 introduces “Default Method” or (Defender methods) new feature, which allows developer to add new methods to the interfaces without breaking the existing implementation of these interface. It provides flexibility to allow interface define implementation which will use as default in the situation where a concrete class fails to provide an implementation for that method.
public interface A {
default void foo(){
System.out.println("Calling A.foo()");
}
}
public class ClassAB implements A {
}
There is one common question that people ask about default methods when they hear about the new feature for the first time:
What if the class implements two interfaces and both those interfaces define a default method with the same signature?
Example to illustrate this situation:
public interface A {
default void foo(){
System.out.println("Calling A.foo()");
}
}
public interface B {
default void foo(){
System.out.println("Calling B.foo()");
}
}
public class ClassAB implements A, B {
}
This code fails to compile with the following result:
java: class Clazz inherits unrelated defaults for foo() from types A and B
To fix that, in Clazz, we have to resolve it manually by overriding the conflicting method:
public class Clazz implements A, B {
public void foo(){}
}
But what if we would like to call the default implementation of method foo() from interface A instead of implementing our own.
It is possible to refer to A#foo() as follows:
public class Clazz implements A, B {
public void foo(){
A.super.foo();
}
}
Those methods are called default methods. Default method or Defender method is one of the newly added features in Java 8.
They will be used to allow an interface method to provide an implementation used as default in the event that a concrete class doesn't provide an implementation for that method.
So, if you have an interface, with a default method:
public interface Hello {
default void sayHello() {
System.out.println("Hello");
}
}
The following class is perfectly valid:
public class HelloImpl implements Hello {
}
If you create an instance of HelloImpl:
Hello hello = new HelloImpl();
hello.sayHello(); // This will invoke the default method in interface
Useful Links:
Updated Oracle Tutorial
Everything about Java 8
Defender Methods
I did a bit of research and i found the following. Hope this helps.
Existing problem
Normal interface methods are declared as abstract and must be defined in the class that implements the interface. This 'burdens' the class implementer with the responsibility to implement every declared method. More importantly, this also means that extending an interface is not possible after 'publication'. Otherwise, all implementers would have to adapt their implementation, breaking backwards source and binary compatibility.
Solution adopted in Java 8
To cope with these problems, one of the new features of JDK 8 is the possibility to extend existing interfaces with default methods. Default methods are not only declared, but also defined in the interface.
Important points to note
Implementers can choose not to implement default methods in
implementing class.
Implementers can still override default
methods, like regular non-final class methods can be overridden in
subclasses.
Abstract classes can even (re)declare default methods
as abstract, forcing subclasses to reimplement the method (sometimes
called 're-abstraction').
Basicaly I have a need for several methods that do the same thing but with different parameters the sub-classes can chose from, and still force the implementation.
Is this a correct approach/design ?
EDIT: I have edited the addItem() body, these methods contain the final logic that is used to handle the passed parameters
public abstract Class A {
public abstract void addItemImpl()
addItem(String s) {
// do stuff
}
addItem(Collection c) {
// do stuff
}
addItem(Item item) {
// do stuff
}
}
public Class B extends A {
addItemImpl() {
addItem("text, text2")
}
}
public Class C extends A {
addItemImpl() {
addItem([item, item2])
}
}
No, this will not work.
You will not be able to define the "doStuff()" method because you have to handle the parameters. You provide not enough information to give you detailed help. But it's possible that generics might come in handy:
public abstract Class A<T> {
public addItem(T t) {
// dostuff with t
}
}
public Class B extends A<String> {
}
public Class C extends A<Collection> {
}
This is a perfect case for: Favor composition over inheritance.
Your subclasses don't fully benefit from the superclass and don't depend on its implementation details. Then define an interface for the contract B and C must obey (addItemImpl()) and compose them with A.
Ask yourself: is B really an A? is C really and A?
What you have is technically correct, but with out knowing what addItem actually does it is difficult to know if this is the best solution. My guess would be that there probably is a better way.
If addItem essentially set values to be used in the doStuff, I would just do that work in the Class B and C instead. Any others that need to do it the same way as B could extend it instead of A.
Edit: Based on your edit, I would say this is probably a bad example to use an abstract class. There is no truely shared functionality. An interface would be more appropriate as you need a different implementation for each. You are just trying to hide that inside an abstract class. I would change A to an interface along with using generics.
Only go the abstract class route if there is actually shared code that is exactly the same in all the classes without having to do any tricks to make it work (like above).
If you need force implementation for few methods, then Abstract methods are ideal.
But be careful only the very first Non-Abstract sub-class of the Super-class is bound to implement all the abstract methods in it....
Can you have a class which implements an interface, and choose whether to use the methods in the interface during instantiation of this class? Therefore having object A which uses the interface and object B which does not use it.
Thanks
Updated:
Assuming you have a Professor class and this class implements an interface called Employer, which has employ(rAssist x) abstract method.
Now I want to instantiated 2 objects from the Professor class implementing this interface Object A - Professor can employ a research assistant and Object B - Professor cannot employ research assistants.
Can you have a class which implements an interface, and choose whether to use the methods in the interface during instantiation of this class?
No, if class C implements the interface, then all instances of C will provide the methods declared in the interface.
What you can do is something like
class MyClass implements MyInterface {
#Override
void interfaceMethod() {
System.out.println("Interface method");
}
}
and then do
MyClass x = new MyClass();
MyClass y = new MyClass() {
#Override
void interfaceMethod() {
throw new UnsupportedOperationException();
}
};
In effect, x supports the use of interfaceMethod while y does not. Note however that...
The usage of y.interfaceMethod is not prevented at compile-time, i.e. it will not be enforced by the type system.
With this solution, you are in fact creating an (anonymous) subclass of MyClass and assigning an instance of it to y.
Do you mean you want class A and Class B to implement a common Interface but you dont want to implement all methods in Class B?
An Interface in simple terms means it is sort of a contract and all the classes which implement it should follow that contract.So if you want Class B to implement the interface , Class B should also follow the same contract. But if you dont want to implement any methos you can always do this.
class ISampleInterface {
void sampleMethod();
void optionalMethod();
}
Class A implements ISampleInterface {
void sampleMethod() {
//Your Implementation
}
void optionalMethod() {
//Your Implementation
}
}
class B implements ISampleInterface {
void sampleMethod() {
//Your Implementation
}
void optionalMethod() {
throw new UnsupportedMethodException();
}
}
No, that's not the point of an Interface.
An Interface is contract that guarantees that implementations WILL implement it's signature
The idea of interface is to establish a obligation for the class that implements the interface.
If your's is a requirement, you can use the java.lang.reflect.Method reflection class to change the visibility of the method at runtime. However, this is not a clean way.
1. Interfaces were introduced in Java because Multiple Inheritance was not allowed in Java.
2. But as far as Design Pattern are concerned, following are the uses..
- To implement certain Roles.
Consider Dog a Super class, but then Pet dog and Wild dog can be interfaces, which
can be implemented by the Sub Classes of Dog class.
- Used when Behaviors keeps changing.
Consider you have a Class Drawing, and paint method() in it, now paint can be stroking, shading, etc...
You must Encapsulate such behaviors in an Interface or an Abstract class.
Is there any way to NOT implement all of the methods of an interface in an inheriting class?
The only way around this is to declare your class as abstract and leave it to a subclass to implement the missing methods. But ultimately, someone in the chain has to implement it to meet the interface contract. If you truly do not need a particular method, you can implement it and then either return or throw some variety of NotImplementedException, whichever is more appropriate in your case.
The Interface could also specify some methods as 'default' and provide the corresponding method implementation within the Interface definition (https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html). These 'default' methods need not be mentioned while implementing the Interface.
The point of an interface is to guarantee that an object will outwardly behave as the interface specifies that it will
If you don't implement all methods of your interface, than you destroy the entire purpose of an interface.
We can override all the interface methods in abstract parent class and in child class override those methods only which is required by that particular child class.
Interface
public interface MyInterface{
void method1();
void method2();
void method3();
}
Abstract Parent class
public abstract class Parent implements MyInterface{
#Override
public void method1(){
}
#Override
public void method2(){
}
#Override
public void method3(){
}
}
In your Child classes
public class Child1 extends Parent{
#Override
public void method1(){
}
}
public class Child2 extends Parent{
#Override
public void method2(){
}
}
I asked myself the same question, and then learned about Adapters. It solved my problem, maybe it can solve yours. This explains it very well : https://blogs.oracle.com/CoreJavaTechTips/entry/listeners_vs_adapters
You can do that in Java8. Java 8 introduces “Default Method” or (Defender methods) new feature, which allows a developer to add new methods to the Interfaces without breaking the existing implementation of these interfaces.
It provides flexibility to allow Interface define implementation which will use as default in the situation where a concrete Class fails to provide an implementation for that method.
interface OldInterface {
public void existingMethod();
default public void DefaultMethod() {
System.out.println("New default method" + " is added in interface");
}
}
//following class compiles successfully in JDK 8
public class ClassImpl implements OldInterface {
#Override
public void existingMethod() {
System.out.println("normal method");
}
public static void main(String[] args) {
ClassImpl obj = new ClassImpl ();
// print “New default method add in interface”
obj.DefaultMethod();
}
}
Define that class as an abstract class. However, you must implement those unimplemented methods when you want to create an instance of it (either by using a subclass or an anonymous class).
It is possible and it is easy. I coded an example.
All you have to do is inherit from a class that does implement the method. If you don't mind a class that is not instantiable, then you can also define an abstract class.
If you want an instantiable class, it is not possible. You may try to define an abstract class, though.
If you try to implement an interface and you find yourself in a situation where there is no need to implement all of them then, this is a code smell. It indicates a bad design and it violates Liskov substitution principle. Often this happens because of using fat interface.
Also sometimes this happens because you are trying to implement an interface from an external dependency. In this case, I always look inside the source code to see if there is any implementation of that interface which I can either use it directly or subclass it and override methods to my needs.
We can use Adapter classes ,which reduces complexcity by not making mandatory to implement all the methods present in the interface
Adapter class is a simple java class that implements an interface with only EMPTY implementation .
Instead of implementing interface if we extends Adapter class ,we provide implementation only for require method
ex--- instead of implementing Servlet(I) if we extends GenericServlet(AC) then we provide implementation for Service()method we are not require to provide implementation for remaining meyhod..
Generic class Acts as ADAPTER class for Servlet(I).
yes possible below shown is the way
interface Test {
void m() throws NullPointerException;
}
class Parent {
// Parent class doesn't implements Test interface
public void m() {
System.out.println("Inside Parent m()");
}
}
class Child extends Parent implements Test {
}
public class Program {
public static void main(String args[]) {
Child s = new Child();
s.m();
}
}