Why should we use Interface?

Why should we use Interface?

In this post, we will examine the concept of the interface in Java.

Like classes, the interface can have methods and fields. But the methods are indicative only. What should happen when creating a class can be defined with the interface. Careful, we say it is definable. Details are determined in the applied class.

The purpose of the methods in Interface is to tell what to do, and it is not responsible for how to do it.

If a class does not implement all the methods in the implemented interface, it should be defined as an abstract class.


If you do not have a specific way to access a property, you can create prototype scope objects instead of creating a Singleton object.

If the class you will use contains core business logic and it is the only class for this mission, then there is no need to create an interface, just create the class.

If a class gives information about details and doesn't do the core job, then we can make it more descriptive with an interface. We will indicate that it is not a core class but a detailed explanation.

The interface helps follow the Dependency Rule and Dependency Inversion Principle (D in SOLID) rule. In other words, it decreases the dependence of upper-class classes on lower-level classes. When the behavior changes in the lower level classes, the upper classes should not be affected. We can achieve this with the interface. Robert C. Martin talks about the usage in the Clean Architecture book. Listen to him.


interface <interface_name> {

    // metods, fields
    // fields are public, abstract, and final
    // metods are public, abstract
}

We use the "implements" keyword when we use an interface in a class.

public class ExampleClass implements IExample
{
     @Override
     public void exampleMetod()
     {
         // body of the method 
     }
}

An interface helps to create standard behavior when there are multiple classes with the same operating logic. In this case, the use of the interface gives you to get an idea about behaviors quickly.

When using an interface, it provides general abstraction. So why use the interface when there are abstract classes? Although they serve the same purpose, your variable definitions in the abstract class may be non-final variables, while the interface does not allow this. (Keep it under your hat, it is inadvisable to define variables in the interface.) You can declare only the methods you want in the abstract class and fill the body in the others. Interface only allows declaration (default definitions are allowed with JDK 8). For these reasons, it is very functional as it presents clear lines when setting general rules with the interface.

Java doesn't provide inheriting more than one class., we can include more than one feature group in the class with the interface. Java provides only one class inheriting. The use of the interface gives a chance to implement more than one feature group. Thus, we can make our class stronger with the use of the Interface. We can use both inheritance and interface.

An interface can inherit another interface in itself. It doesn't have to inherit just one interface like classes. It can extend multiple interfaces. In addition to its own methods, it also has the methods of the interfaces it extends.

public interface ISuperExample extends ISubExample1,ISubExample2 {
   public void exampleMethod();
}

It allows us to apply loose coupling. For example, we are developing a painting feature for one picture format. Our image format was png when we first started, but there is a possibility that different formats will come later. At this point, we complicate things if we do separate operations for all types. But if we write an interface like the one below and define a variable over the interface while using it, we will speed up the jobs that have already invested in future missions.

Let's define the final color and our paint method in the interface:

interface IPictureFormat
{
 static final Color = Color.RED;
 void paint();
}

Let's implement the interface while operating in png format:

public class PngPaint implements IPictureFormat
{
    @Override
    void paint()
    {
      // paint for png format
    }
}

We can use the class to which the interface is directly applied, or we can include all the classes that it is applied to by defining with the interface. In the example below, whatever implements the IPictureFormat interface can come to the PictureFormatter class as a variable.

public class PictureFormatter{ 
  private IPictureFormat format;
  public PictureFormatter(IPictureFormat format)
  {    
    this.format=format;
  }
  public void work(){
    format.paint();
  }
}

With JDK 8, it is allowed to define static methods in the interface. You can define a static method in the interface as follows and access it directly through the interface. You do not have to have an object. It can be useful for general methods related to Interface.

interface IExample
{
   static void giveResult(){
      System.out.println("Example metod");
   }
}

We can call the above class as follows. It will print "Example method" as the output:

IExample.giveResult();

To implement Interface must be class, abstract, nested class, enum, or dynamic proxy.


Sometimes you will see empty interface contents implemented. when I first saw it, I have asked the question: "So why was it implemented, and what did it do?" We create an is-a relationship by specifying an empty interface. Maybe we don't take a method from within the interface, but we include the class in a group. We are using a supportive structure of what its function is. Of course, first of all, the names of methods and variables should be meaningful. If not, whatever you do, your code will look like garbage.


You can also create an interface in an interface or an interface in a class. When you create an interface in the class, you can access it with the class_name.interface_name. When you create an interface in an interface, you can reach the outermost interface name, which we call the parent interface, by using the inner interface (child) names, parent_interface_name.child_interface_name.

If you want to see its usage with a brief example, you can look at the project below:

Github project


We can also create a type-specific interface that we call a generic interface. They work specific to the type we have identified. Let's try to set an example for this. Let's say we're making product lists for a factory. Our first task is to list the car product line and then work on other products in the factory. For the future of other products, we created an interface as follows. We implemented the interface as in the following code snippet. We can now use the class for cars.

public interface IFactory{
    public Car product();
}

Implement:

public class CarProduction implements IFactory{
  public Car product()
  { 
    return new Car();
  }
}

Use:

IFactory carProduction = new CarProduction(); Car car = (Car) carProduction.product();

And what do we see when the process is over. Yes, we provided a bit of abstraction with IFactory, but we still have a clear connection with the Car object. We can get rid of this situation by giving generic types.

Let's make a small change in Interface:

public interface IFactory <T>{
    public T product();
}

We broke the Car object dependency on Interface. So what will change when implementing?

public class CarProduction implements IFactory<T>{
  public Car product()
  { 
    return new Car();
  }
}
public class TruckProduction implements IFactory<T>{
  public Truck product()
  { 
    return new Truck();
  }
}

We made two different types of production and got the results. Notice that we use the product() method from the interface for both. In both, the results are different types. Thus, we have obtained interfaces, not for a single production line but multiple production lines. We reach the class as follows:

IFactory<Car> carProduction = new CarProduction();
Car car = carProduction.product();

IFactory<Truck> truckProduction = new TruckProduction();
Truck truck = truckProduction.product();

You can access the full example above from my Github project


As a result:

  • Without being implemented anywhere, the interface is not used as an object.
  • A class can implement multiple interfaces.
  • An interface can extend another interface.
  • When a class implements an interface, it must fill the body of all the methods.
  • All methods in Interface are public and abstract. Field definitions are public, static, and final. It is, even if you don't type these keywords.
  • Interfaces are used to provide multiple inheritances.
  • Interfaces are used to provide loose coupling.

Resources: