Interfaces - BasicsS2C Home « Interfaces - Basics

This lesson looks at interfaces and the contracts we provide when using them. What does the last sentence actually mean? To explore this we will add a new class to our Vehicle hierarchy and take the explanation forwards from there:

interface 1

When we last visited Vehicle Town, we had made the Vehicle and Truck classes abstract to stop them being instantiated. We also made the load() method abstract in the Truck class to ensure the first concrete subclass had to implement it. Meanwhile back in Vehicle town the amount of people is putting a strain on our bus network and the budget. The mayor wants us to bring in taxis and make people queue and pay for buses and taxis.

interface 2




We could introduce a new Taxi class with a couple of new methods that we also want to add to the Bus class.

interface 3




We could introduce a new Taxi class with a couple of new methods that we put into the Vehicle superclass.

interface 4




We could introduce a new Taxi class with a couple of new abstract methods that we put into the Vehicle superclass.

interface 5




We decide to create a new interface called PublicTransport with the new queue() and payFare() methods and implement the interface in the appropriate classes.

Using the interface keyword Top

So, we have now decided to use an interface to put our new queue() and payFare() methods in, we can talk about and then code up the interface for this purpose. We create an interface using the interface keyword, instead of class in the defintion. Up until Java8 all interface methods were implicitly declared as public and abstract and had no body, thus providing a contract which an implementing class would have to honour by creating implementations for each method within the implemented interface.

This design also meant that the designers of an interface couldn't update it with new methods without breaking the contract of every implementation class that would now have to be refactored to include the new implementations. The Java designers got around this problem by introducing interface default methods which have a body but do not need to be implemented thus avoiding breaking any existing contracts.

We will discuss interface default methods along with static methods which are also allowed in interfaces from Java8 onwards in the next lesson. Implementable methods, those with no body, are still implicitly declared as public and abstract, need to be implemented and are discussed here. Ok, Lets code up our new PublicTransport interface:


package com.server2client;
/*
 The PublicTransport interface
*/ 
public interface PublicTransport {

    void queue(int queue);  // The public and abstract modifiers are added by the compiler
    void payFare(int money);  // The public and abstract modifiers are added by the compiler
}

build PublicTransport interface
Screenshot 1. Building the PublicTransport interface.

The above screenshot shows the output of building our PublicTransport interface.

Using the implements keyword Top

Now we have coded up our new PublicTransport interface to use it in a class we use the implements keyword in the classes we want to implement our interface in. We will start with our existing Bus class, just add implements PublicTransport to the class declaration:


package com.server2client;
/*
 A Bus Class
*/ 
public class Bus extends Vehicle implements PublicTransport {

    ... 
}

run Bus class implementation
Screenshot 2. Runnning the Bus class implementation.

The above screenshot shows the output of running our updated Bus class. We get a compiler error because we haven't implemented the abstract methods from the PublicTransport interface. Just like with abstract classes we need to honour the contract by implementing all abstract methods in the first concrete subclass:


package com.server2client;
public class Bus extends Vehicle implements PublicTransport {
    /*
      Our queue() implementation
    */ 
    void queue(int people) {
        System.out.println("There are " + people + " people waiting for a bus.");
        
    }
    /*
      Our payFare() implementation
    */ 
    void payFare(int fare) {
        System.out.println("This bus journey will cost you " + fare + " pounds.");
        
    }
    ... 
}

run Bus class implementation
Screenshot 3. Runnning the Bus class implementation.

The above screenshot shows the output of running our updated Bus class. We forgot to give our implementations the public access modifier and abstract implementations can't be more restrictive. If you remember from the lesson on abstraction, implementing an abstract method is the same as overriding a method from a concrete superclass, therefore the same rules apply as those for overriding method rules. Add the public access modifier to the front of our new methods and recompile the class. Following is a test class to make sure everything still works in our Bus class:


package com.server2client;
/*
 Test class for Bus
*/ 
public class TestBus {

    public static void main (String[] args) {
        Bus a1 = new Bus();
        a1.setChassis("4-axle chassis");
        a1.setMotor("12 stroke");
        a1.setWheels(8);
        a1.setConductor(true);
        System.out.println("Our bus has a " + a1.getChassis() + ", " + a1.getMotor() 
                                            + " motor and has " + a1.getWheels() + " wheels.");
        if (a1.getConductor()) {
            System.out.println("This bus has a driver and a conductor."); 
        } else {
            System.out.println("This bus has a driver only."); 
        }                                    
        a1.service(3); 
        a1.carry(60); 
        a1.load("people."); 
        a1.queue(12); 
        a1.payFare(2); 
    }
}

run  Bus class implementation
Screenshot 4. Runnning the TestBus class.

The above screenshot shows the output of running our TestBus test class, everything works fine. We will code up our Taxi class as well for a bit of practice and for use later on:


package com.server2client;
public class Taxi extends Vehicle implements PublicTransport {
    /*
      Our queue() implementation
    */ 
    public void queue(int people) {
        System.out.println("There are " + people + " people waiting at the taxi rank.");
        
    }
    /*
      Our payFare() implementation
    */ 
    public void payFare(int fare) {
        System.out.println("This taxi ride will cost you " + fare + " pounds.");
        
    }
}

Implementing Multiple Interfaces Top

It is also perfectly legal to implement multiple interfaces and the following code shows the syntax for doing this:


package com.server2client;
public class Taxi extends Vehicle implements PublicTransport, Serializable, Runnable {
    ...    
}

Related Quiz

OO Concepts Quiz 10 - Interfaces

Lesson 10 Complete

In this lesson we looked at interfaces and the contracts we provide when using them.

What's Next?

In the next lesson we examine interface default and interface static methods which were both introduced in Java8.