0

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.

Logan
  • 2,445
  • 4
  • 36
  • 56

4 Answers4

2

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).

matoni
  • 2,479
  • 21
  • 39
  • So default method can act as a method which will be used to call existing methods in certain order, which will mostly be common for all classes implementing in. Yeah, makes sense. Thanks. – Logan Aug 22 '18 at 13:21
1

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.

daniu
  • 14,137
  • 4
  • 32
  • 53
1

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.

Thiyagu
  • 17,362
  • 5
  • 42
  • 79
  • Thanks for this example. Modifying interface1 will be my only option then. Now it makes much more sense. – Logan Aug 22 '18 at 13:19
1

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.

Mạnh Quyết Nguyễn
  • 17,677
  • 1
  • 23
  • 51