Search the courses, subjects, tracks, games and features, or jump straight to a page.
Learn it your way
A short class with Sarah and her students. The other ways are under More.
Sign up free to listen. Transcripts are free to read.
Look at the array in ShapeDemo. It is declared as Shape[], yet it holds Rectangle and Circle objects. Why is that allowed?
Because Rectangle and Circle both implement Shape, so each object is also a Shape.
Exactly. Now, when the loop calls s.area(), how does Java decide which area() to run?
It looks at the actual object, not at the reference. For the Circle object it uses the circle formula.
Right. That is dynamic method dispatch, decided at run time. So the same line gives 40.0, then 153.94, then 16.0.
So if we add a Triangle class later, the loop stays exactly the same?
Not one character changes. You write Triangle, make it implement Shape, and put a Triangle object in the array.
In the interface Data, PI is written without static or final. What is it really?
A constant. Every field in an interface is public, static and final automatically.
Correct. So could the Cylinder class write PI = 3.14 inside volume()?
No. A final variable cannot be given a new value, so it would not compile.
Good. Now the SmartPhone class. How many classes can a Java class extend, and how many interfaces can it implement?
Only one class, but as many interfaces as it needs, separated by commas after implements.
And that is how Java offers multiple inheritance safely: the interfaces only promise methods, and the class writes one body for each.
Look at bill(Payment p, double amount). Does this method know whether the customer pays by UPI or in cash?
No. It only knows that whatever object it receives has a pay() method.
That is loose coupling. Suppose the shop starts accepting cards. What must change in bill()?
Nothing. We only write a CardPayment class that implements Payment.
Exactly. One last check: if UpiPayment had an extra method checkBalance(), could bill() call p.checkBalance()?
No. The compiler allows only the methods declared in Payment, because p has the type Payment.
Well done. Remember it this way: the reference type decides what you may call, and the object decides which body runs.
A variable or array of an interface type can hold objects of every class that implements the interface.
The actual object, not the reference type, decides which method body runs at run time.
Fields in an interface are public, static and final, and can be read as InterfaceName.FIELD without an object.
A class can implement several interfaces, separated by commas, but can extend only one class.
A method with an interface parameter works with every present and future implementing class.
Through an interface reference you may call only the methods the interface declares.
An interface can extend two other interfaces, and one class can satisfy all of them; this program prints three lines that begin with Printing:
interface Printer {
void print(String document);
}
interface DocumentScanner {
String scan();
}
// An interface can extend more than one interface
interface AllInOne extends Printer, DocumentScanner {
void copy();
}
class OfficeMachine implements AllInOne {
public void print(String document) {
System.out.println("Printing: " + document);
}
public String scan() {
return "scanned page";
}
public void copy() {
print(scan());
}
}
public class AllInOneDemo {
public static void main(String[] args) {
AllInOne machine = new OfficeMachine();
machine.print("Report card");
machine.copy();
Printer p = machine; // also usable wherever a Printer is expected
p.print("Timetable");
}
}A class can extend one class and implement an interface at the same time, with extends written before implements; the dog eats as an Animal and plays as a Pet:
class Animal {
String name;
Animal(String name) {
this.name = name;
}
void eat() {
System.out.println(name + " is eating");
}
}
interface Pet {
void play();
}
// extends comes first, then implements
class Dog extends Animal implements Pet {
Dog(String name) {
super(name);
}
public void play() {
System.out.println(name + " fetches the ball");
}
}
public class PetDemo {
public static void main(String[] args) {
Dog d = new Dog("Bruno");
d.eat(); // inherited from the class Animal
d.play(); // promised by the interface Pet
Pet p = d;
p.play();
}
}Through a Shape reference only Shape's methods can be called; to use a method that only Circle has, check with instanceof and cast back (prints Area: 79 and Diameter: 10.0):
interface Shape {
double area();
}
class Circle implements Shape {
double radius;
Circle(double radius) {
this.radius = radius;
}
public double area() {
return Math.PI * radius * radius;
}
double diameter() { // Circle's own method, not in Shape
return 2 * radius;
}
}
public class CastDemo {
public static void main(String[] args) {
Shape s = new Circle(5);
System.out.println("Area: " + Math.round(s.area()));
// s.diameter() would not compile: Shape declares no diameter()
if (s instanceof Circle) {
Circle c = (Circle) s;
System.out.println("Diameter: " + c.diameter());
}
}
}The reference says what you may call, the object says which body runs, and that is all.
A school sports day has one rule for every event: when the whistle blows, start. The sprinter runs, the swimmer dives and the jumper leaps. The whistle is the interface method, and each athlete is an object that starts in its own way.
Please Stay Fixed: Public, Static, Final, the three hidden words in front of every interface field.
E.I.: Extends first, Implements second, as in class Dog extends Animal implements Pet.
Term
If Shape is an interface, can you write new Shape()?
Click to flip
Term
What access modifier must an implementing class give to the interface's methods?
Click to flip
Term
What is double PI = 3.142 when it is written inside an interface?
Click to flip
Term
How does one class implement two interfaces?
Click to flip
Term
When s.area() is called on a Shape reference, whose area() runs?
Click to flip
The keyword with which a class promises to define every abstract method of one or more interfaces.
A variable whose type is an interface; it can refer to an object of any class that implements that interface.
The run-time choice of which method body to execute, made from the class of the actual object rather than the type of the reference.
A field declared in an interface; it is automatically public, static and final, and is read as InterfaceName.FIELD.
Writing code that depends on an interface rather than on particular classes, so that classes can be added or changed without changing that code.
An operator that tests whether an object belongs to a class or implements an interface, giving true or false.
A class that implements an interface but leaves some of its methods undefined; such a class must be declared abstract.
This lesson teaches interfaces through complete worked examples: one interface with many implementing classes, constants inside an interface, a class that implements two interfaces, and an interface used as a parameter type.
Knowing the rules of interfaces is not the same as using them. Here we read four complete Java programs and trace their output. You will see a Shape interface drive an array of different shapes, an interface constant used in a volume formula, a SmartPhone class that is both a Camera and a MusicPlayer, and a billing method that works with any Payment class. Each example shows how the reference type decides which methods may be called, while the actual object decides which method body runs.
The earlier lessons defined an interface, listed its features and showed its syntax. This lesson puts those rules to work. Every program below is complete, so you can run it and compare the output with the output shown.
Three rules are used in every example:
public and abstract. A field declared in an interface is automatically public, static and final, so it must be given a value.implements and must define every abstract method of that interface as public. If it leaves any method undefined, the class must itself be declared abstract.new Shape() is a compile-time error), but a variable of the interface type can refer to an object of any class that implements it.The interface Shape promises three methods. Rectangle and Circle keep that promise in their own ways, and the main() method treats them all simply as shapes.
interface Shape {
double area();
double perimeter();
String name();
}
class Rectangle implements Shape {
private double length, breadth;
Rectangle(double length, double breadth) {
this.length = length;
this.breadth = breadth;
}
public double area() {
return length * breadth;
}
public double perimeter() {
return 2 * (length + breadth);
}
public String name() {
return "Rectangle";
}
}
class Circle implements Shape {
private double radius;
Circle(double radius) {
this.radius = radius;
}
public double area() {
return Math.PI * radius * radius;
}
public double perimeter() {
return 2 * Math.PI * radius;
}
public String name() {
return "Circle";
}
}
public class ShapeDemo {
static double round2(double x) {
return Math.round(x * 100) / 100.0;
}
public static void main(String[] args) {
Shape[] shapes = { new Rectangle(8, 5), new Circle(7), new Rectangle(4, 4) };
double total = 0;
for (Shape s : shapes) {
System.out.println(s.name() + ": area = " + round2(s.area())
+ ", perimeter = " + round2(s.perimeter()));
total = total + s.area();
}
System.out.println("Total area = " + round2(total));
}
}Output:
Rectangle: area = 40.0, perimeter = 26.0
Circle: area = 153.94, perimeter = 43.98
Rectangle: area = 16.0, perimeter = 16.0
Total area = 209.94
How it works: the array has the interface type Shape[], yet it holds Rectangle and Circle objects, because each of them is a Shape. The single line s.area() runs the rectangle formula (8 × 5 = 40) for the first object, the circle formula (π × 7 × 7 ≈ 153.94) for the second and the rectangle formula again (4 × 4 = 16) for the third. Java chooses the body at run time from the actual object. This is called dynamic method dispatch. To add a triangle later, you would write a Triangle class that implements Shape and put a Triangle object in the array; the loop would not change.
ISC questions often describe an interface with a data member and a method. The data member is a constant that every implementing class can use.
interface Data {
double PI = 3.142; // a constant: public, static and final
double volume(); // an abstract method: public and abstract
}
class Cylinder implements Data {
double radius, height;
Cylinder(double radius, double height) {
this.radius = radius;
this.height = height;
}
public double volume() {
return PI * radius * radius * height;
}
}
public class VolumeDemo {
public static void main(String[] args) {
Cylinder c = new Cylinder(7, 10);
System.out.println("PI read through the interface = " + Data.PI);
System.out.println("Volume of the cylinder = " + c.volume());
}
}Output:
PI read through the interface = 3.142
Volume of the cylinder = 1539.58
How it works: PI was written without static or final, but the compiler adds them, so PI is a constant that belongs to the interface. That is why main() can read it as Data.PI without creating any object. The volume is 3.142 × 7 × 7 × 10 = 1539.58. A statement such as PI = 3.14; inside Cylinder would not compile, because a final variable cannot be given a new value.
A Java class can extend only one class, but it can implement any number of interfaces, listed after implements and separated by commas.
interface Camera {
void takePhoto();
}
interface MusicPlayer {
void playSong(String title);
}
class SmartPhone implements Camera, MusicPlayer {
private String model;
SmartPhone(String model) {
this.model = model;
}
public void takePhoto() {
System.out.println(model + " clicks a photo");
}
public void playSong(String title) {
System.out.println(model + " plays " + title);
}
}
public class PhoneDemo {
public static void main(String[] args) {
SmartPhone phone = new SmartPhone("Phone X");
Camera cam = phone; // the same object, seen as a Camera
MusicPlayer player = phone; // the same object, seen as a MusicPlayer
cam.takePhoto();
player.playSong("Raag Yaman");
System.out.println(phone instanceof Camera);
System.out.println(phone instanceof MusicPlayer);
}
}Output:
Phone X clicks a photo
Phone X plays Raag Yaman
true
true
How it works: one SmartPhone object is referred to by three variables of three different types. Through cam you may call only takePhoto(), and through player only playSong(), because the compiler checks calls against the reference type. The instanceof operator confirms that the object is both a Camera and a MusicPlayer. This is how interfaces give Java the benefit of multiple inheritance: each interface only promises methods, and the class supplies exactly one body for each.
When a method's parameter has an interface type, the method works with every class that implements the interface, including classes written later.
interface Payment {
boolean pay(double amount);
}
class UpiPayment implements Payment {
private double balance;
UpiPayment(double balance) {
this.balance = balance;
}
public boolean pay(double amount) {
if (amount <= balance) {
balance = balance - amount;
System.out.println("Paid Rs " + amount + " by UPI");
return true;
}
System.out.println("UPI payment failed: low balance");
return false;
}
}
class CashPayment implements Payment {
public boolean pay(double amount) {
System.out.println("Received Rs " + amount + " in cash");
return true;
}
}
public class Checkout {
// bill() knows only the Payment interface, not the classes behind it
static void bill(Payment p, double amount) {
if (p.pay(amount)) {
System.out.println("Bill closed");
} else {
System.out.println("Bill still open");
}
}
public static void main(String[] args) {
bill(new UpiPayment(500), 350);
bill(new UpiPayment(100), 350);
bill(new CashPayment(), 120);
}
}Output:
Paid Rs 350.0 by UPI
Bill closed
UPI payment failed: low balance
Bill still open
Received Rs 120.0 in cash
Bill closed
How it works: bill() depends only on the interface, so it never needs to know how a payment is made. This is loose coupling. If the shop starts accepting cards, a new CardPayment class that implements Payment can be passed to bill() without changing a single line of bill().
Since Java 8 an interface may also contain default and static methods that have bodies. The examples here use the classic form, with abstract methods and constants, which is the form ISC questions use.