Interfaces - BasicsJ8 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:
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 info.java8;
/*
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
}
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 info.java8;
/*
A Bus Class
*/
public class Bus extends Vehicle implements PublicTransport {
...
}
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 info.java8;
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.");
}
...
}
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 info.java8;
/*
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);
}
}
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 info.java8;
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 info.java8;
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.