Java Arena
Step 3 of 9

An interface as a variable's type

An interface is a type, just like a class. It can be the type of a variable, and such a variable can refer to an object of any class that implements the interface:

Main.java
public class Main {
    public static void main(String[] args) {
        Switchable device = new Heater("hall", 21);
        device.turnOn();
        System.out.println(device);

        device = new GardenLight("patio");
        System.out.println(device.isOn());
        device.turnOn();
        System.out.println(device);
    }
}
Switchable.java
public interface Switchable {
    void turnOn();
    void turnOff();
    boolean isOn();
}
Heater.java
public class Heater implements Switchable {
    private String room;
    private int degrees;
    private boolean on;

    public Heater(String room, int degrees) {
        this.room = room;
        this.degrees = degrees;
        this.on = false;
    }

    @Override
    public void turnOn() {
        this.on = true;
    }

    @Override
    public void turnOff() {
        this.on = false;
    }

    @Override
    public boolean isOn() {
        return this.on;
    }

    public int getDegrees() {
        return this.degrees;
    }

    @Override
    public String toString() {
        if (this.on) {
            return "Heater in the " + this.room + ": on, " + this.degrees + " degrees";
        }
        return "Heater in the " + this.room + ": off";
    }
}
GardenLight.java
public class GardenLight implements Switchable {
    private String place;
    private boolean on;
    private int switchOns;

    public GardenLight(String place) {
        this.place = place;
        this.on = false;
        this.switchOns = 0;
    }

    @Override
    public void turnOn() {
        if (!this.on) {
            this.on = true;
            this.switchOns++;
        }
    }

    @Override
    public void turnOff() {
        this.on = false;
    }

    @Override
    public boolean isOn() {
        return this.on;
    }

    @Override
    public String toString() {
        return "Garden light (" + this.place + "): " + this.switchOns + " switch-ons";
    }
}
Output
Heater in the hall: on, 21 degrees
false
Garden light (patio): 1 switch-ons
  • Switchable device = new Heater("hall", 21); compiles because Heater implements Switchable: a Heater is a Switchable. It's the same idea as module 34's Adventurer hero = new Knight("Oren");, with an interface in place of the superclass.
  • Calls on device run the object's own methods: Heater's while device refers to the heater, and GardenLight's after the assignment.
  • println(device) calls the object's own toString. Every object has Object's methods, so a variable of an interface type can use them too, even though Switchable doesn't list them.

The variable's type decides what you may call

While device refers to the heater, the heater has a getDegrees(). Still, this doesn't compile:

Main.java
public class Main {
    public static void main(String[] args) {
        Switchable device = new Heater("hall", 21);
        System.out.println(device.getDegrees());
    }
}
Switchable.java
public interface Switchable {
    void turnOn();
    void turnOff();
    boolean isOn();
}
Heater.java
public class Heater implements Switchable {
    private String room;
    private int degrees;
    private boolean on;

    public Heater(String room, int degrees) {
        this.room = room;
        this.degrees = degrees;
        this.on = false;
    }

    @Override
    public void turnOn() {
        this.on = true;
    }

    @Override
    public void turnOff() {
        this.on = false;
    }

    @Override
    public boolean isOn() {
        return this.on;
    }

    public int getDegrees() {
        return this.degrees;
    }
}
What javac prints
Main.java:4: error: cannot find symbol
        System.out.println(device.getDegrees());
                                 ^
  symbol:   method getDegrees()
  location: variable device of type Switchable
1 error

javac knows only that device holds some Switchable, and a garden light or a sprinkler has no degrees. These are module 34's two rules again:

  • The variable's type decides which methods you may call. Through a Switchable variable, that's Switchable's three methods (and Object's).
  • The object's class decides which version of a method runs.

So pick the type that fits what the code needs. Code that only switches devices on and off can use Switchable, and then it works with every device. Code that sets the heater's temperature needs a Heater variable.

No objects of an interface

Main.java
public class Main {
    public static void main(String[] args) {
        Switchable device = new Switchable();
    }
}
Switchable.java
public interface Switchable {
    void turnOn();
    void turnOff();
    boolean isOn();
}
What javac prints
Main.java:3: error: Switchable is abstract; cannot be instantiated
        Switchable device = new Switchable();
                            ^
1 error

An interface has no code to run, so there are no Switchable objects as such. Every object comes from a class, and a Switchable variable refers to an object of some class that implements Switchable, or to nothing (null).

An object whose class implements several interfaces fits in a variable of each of them: step 2's robot vacuum can be a Switchable and a Chargeable. Module 36 looks more closely at one object seen through each of its types.

Your task

Challenge 1 of 3

Step 2's laptop and headphones again: the laptop gains 1 percent a minute, the headphones 5, and neither goes above 100. What does this program print?

Challenge 2

Fill in the blank, a type, so that the program compiles. The one variable refers to a laptop first and to headphones later.

Challenge 3

The app has one button that controls one device, chosen when the app starts. The program reads one word, fan or heater. Declare one variable of type Switchable. If the word is fan, give it new CeilingFan(); otherwise give it new Heater("bedroom", 19). Then, after the if, turn the device on and print it, each just once, whichever device it is. The classes are ready. With the input fan, the program prints:

Ceiling fan: speed 1