Designing a Car in Java (Interfaces Explained)

Designing a Car in Java (Interfaces Explained)

Today we will design a car in Java by using Interfaces. Firstly I should define What interface is and How to use it. As we know that in Java we cannot have two parent classes of a single child class, having two parent is called Multiple Inheritance. Hence multiple inheritance is not allowed in Java. But in real life many a times we want to inherit properties of two parent classes in a single child class. For this, we use interfaces. Interfaces are just like abstract classes but which supports multiple inheritance. It's just a collection of body-less methods. However they are not exactly same as Abstract classes, we will see their similarities and differences in between. But for now focus on Interfaces, let's create it!

public interface CarEngine {
    void start();
    void stop();
    void acc();
}
public interface CarBrake {
    void Apply();
}
public interface CarMedia {
    void start();
    void stop();
}

Here we have created three interfaces, you can create them, instead of creating a java class file click on interfaces.

For connecting these interfaces to a class we use implements keyword. Let's create a class and implement CarEngine and CarBrake to it!

static class CarAssembling implements CarEngine,CarBrake{
        @Override
        public void start() {
            System.out.println("Start the Car Engine");
        }

        @Override
        public void stop() {
            System.out.println("Stop the Car Engine");
        }

        @Override
        public void acc() {
            System.out.println("Accelerate the Car Engine");
        }
        @Override
        public void Apply(){
            System.out.println("Apply the break");
        }
    }

So this is the very basics of Syntax of Interfaces. Let's now see some properties of it!

  • Just like abstract classes, we can't create their objects but can use them as reference variable (that also like abstract classes)

  • By default the functions are static and abstract inside interface (See point 4 for reason of static), you can't have non-abstract methods inside Interfaces unlike Abstract classes.

  • Interfaces can't have constructor (Abstract Classes can have!).

  • All the variables inside interfaces are static and final, static because we can't create their objects and final because interfaces can't have constructors so how would you initialize variables if they are not final! This is a property which differs Interfaces from Abstract Classes, as Abstract classes can have non-final variables but non-static variables are not allowed even in Abstract Classes!

Let's Now play with the interfaces

See this code:

public class Assembling {
    public static void main(String[] args) {
     CarAssembling Car1=new CarAssembling();
     Car1.start();
     Car1.acc();
     Car1.Apply();
     Car1.stop();
    }

The output will be:

Start the Car Engine

Accelerate the Car Engine

Apply the break

Stop the Car Engine

So far so good, now see this!

public class Assembling {
    public static void main(String[] args) {
     CarEngine Car1=new CarAssembling();
     Car1.start();
     Car1.acc();
     Car1.Apply();
     Car1.stop();
    }

We can't access Apply()! Why? Because it's not present in CarEngine interface (Remember? Left decide what to access!), this example also show that although we can't create object for interfaces but we can use them as reference variable. Let's move back to our case and add one property to it CarMedia!

public class Assembling {
    public static void main(String[] args) {
     CarMedia Car1=new CarAssembling();
     Car1.start();
     Car1.stop();
    }
    static class CarAssembling implements CarEngine,CarBrake,CarMedia{
        @Override
        public void start() {
            System.out.println("Start the Car Engine");
        }

        @Override
        public void stop() {
            System.out.println("Stop the Car Engine");
        }

        @Override
        public void acc() {
            System.out.println("Accelerate the Car Engine");
        }
        @Override
        public void Apply(){
            System.out.println("Apply the break");
        }
    }
}

Output is:

Start the Car Engine

Stop the Car Engine

This was expected because abstract functions start() and stop() are common to CarEngine and CarMedia and Java just over-rided them to one single method, but isn't it weird? When you turn off the car media, car engine gets off! Let's solve it!

Thought Process:

  1. Now in this problem we shouldn't change the method name of CarEngine or CarMedia because in many real life cases it is not allowed, so we can do one thing, create three classes and then use them in one single class. See this:
class CarMediaFix implements CarMedia{
    @Override
    public void start() {
        System.out.println("Car Media set on");
    }

    @Override
    public void stop() {
        System.out.println("Car Media set off");
    }
}
class CarEngineFix implements CarEngine{
    @Override
    public void start() {
        System.out.println("Start the Car Engine");
    }

    @Override
    public void stop() {
        System.out.println("Stop the Car Engine");
    }
    @Override
    public void acc() {
        System.out.println("Accelerate the Car Engine");
    }
}
class CarBrakeFix implements CarBrake{

    @Override
    public void Apply(){
        System.out.println("Apply the break");
    }
}
  1. Now we have to inject them into one single class in such way that whenever we call StartEngine, engine should get started, also we should not be able to access/modify any of the property of car directly (Isn't it obvious?), we can do this by making them private.

     public class FixingAssembling {
         private CarEngineFix Engine;
         private CarMediaFix Media;
         private CarBrakeFix Brake;
         FixingAssembling(){
             this.Engine=new CarEngineFix();
             this.Media=new CarMediaFix();
             this.Brake=new CarBrakeFix();
         }
         void StartEngine(){
             Engine.start();
         }
         void StopEngine(){
             Engine.stop();
         }
         void AccEngine(){
             Engine.acc();
         }
         void StartMedia(){
             Media.start();
         }
         void StopMedia(){
             Media.stop();
         }
         void ApplyBreak(){
             Brake.Apply();
         }
     }
    
  2. Let's break down this code, firstly we declared three objects, one can initialize them there only but I did using Constructor. Then it's just naming and calling of methods to start the car, turn on the media etc.

  3. Now the problem is solved, as whenever we will create an object for this class, the three objects will be initialized through constructor and then if we call StartEngine() further Engine which is an object of CarEngineFix will call the start() method in CarEngineFix class and hence Engine will be started. See this code!

     public static void main(String[] args) {
         FixingAssembling Car1=new FixingAssembling();
         Car1.StartEngine();
         Car1.AccEngine();
         Car1.StartMedia();
         Car1.StopMedia();
         Car1.ApplyBreak();
         Car1.StopEngine();
         }
    

    Output will be:

    Start the Car Engine

    Accelerate the Car

    Engine Car Media set on

    Car Media set off

    Apply the break

    Stop the Car Engine

Inheriting Interfaces

Now Interfaces can also be inherited using extends keyword, it will just like inheritance of classes but one have to keep in mind that whenever child interface is implemented to any class, abstract methods of parent interface also needs to be over-ridden, which is very obvious thing!

Default Method

Assume that you are in some organization which has very large code base and an for some reason you need to add one more method to some interface which is implemented to many classes. What will you do? If you will simply add a method to that interface then you have to go to each and every class to which interface is implemented and give a body to the method you added. Isn't it a big problem for you? It is! So for solving this, default method is used. By declaring any method as default in an interface you can give it a body there itself, so that default body can be given where that method is not called. See this code:

public interface CarBrake {
    void Apply();
    default void ifnotcalled(){
        System.out.println("Hello");
    }
}

I edited the same interface which is implemented to many classes I used in this blog, you can also do it and see if there is some error (there not be!)

Static Methods

You can create static methods in Interface given that you have to give it a body there itself (this is seeming obvious because static methods will be indepndent of objects, hence they might not get body in future). You can call static methods by class name to which interface is implemented. Suppose interface A is implemented to class B and A has a static method; fxn(), so you can call it by B.fxn();

So, that's it from my side for Interfaces. I hope it will help you!