Contents


Unit 17: Interfaces

Create a named set of behaviors

Comments

Before you begin

This unit is part of the "Intro to Java programming" learning path. Although the concepts discussed in the individual units are standalone in nature, the hands-on component builds as you progress through the units, and I recommend that you review the prerequisites, setup, and unit details before proceeding.

Unit objectives

  • Understand the purpose of an interface
  • Learn the syntax for defining an interface
  • Know how to implement an interface
  • Learn the syntax for using an interface and assigning an interface reference to a variable

Interfaces in action

The following short video addresses all of this unit's learning objectives. I show you what an interface is, how to define and implement an interface, and how the reference assignment rules work. After you watch, you can get a closer look at the code, and a recap of the concepts, by reading this unit's text.

Interfaces: What are they good for?

As you know from the previous unit, abstract methods, by design, specify a contract— through the method name, parameter(s), and return type — but provide no reusable code. Abstract methods — defined on abstract classes — are useful when the way the behavior is implemented is likely to change from the way it's implemented in one subclass of the abstract class to another.

When you see a set of common behaviors in your application (think java.util.List) that can be grouped together and named, but for which two or more implementations exist, you might consider defining that behavior with an interface— and that's why the Java language provides this feature. However, this fairly advanced feature is easily abused, obfuscated, and twisted into the most heinous shapes (as I've witnessed first-hand), so use interfaces with caution.

It might be helpful to think about interfaces this way: They are like abstract classes that contain only abstract methods; they define only the contract but none of the implementation.

Defining an interface

The syntax for defining an interface is straightforward:

public interface InterfaceName {
    returnType methodName(argumentList);
  }

An interface declaration looks like a class declaration, except that you use the interface keyword. You can name the interface anything you want to (subject to language rules), but by convention, interface names look like class names.

Methods defined in an interface have no method body. The implementer of the interface is responsible for providing the method body (as with abstract methods).

You define hierarchies of interfaces, as you do for classes, except that a single class can implement as many interfaces as you want it to. Remember, a class can extend only one class. If one class extends another and implements an interface or interfaces, you list the interfaces after the extended class, like this:

public class Manager extends Employee implements BonusEligible, StockOptionRecipient {
  // And so on
}

An interface doesn't need to have any body at all. The following definition, for example, is perfectly acceptable:

public interface BonusEligible {
}

Generally speaking, such interfaces are called marker interfaces, because they mark a class as implementing that interface but offer no special explicit behavior.

Once you know all that, actually defining an interface is easy:

public interface StockOptionRecipient {
  void processStockOptions(int numberOfOptions, BigDecimal price);
}

Implementing interfaces

To define an interface on your class, you must implement the interface, which means that you provide a method body that provides the behavior to fulfill the interface's contract. You use the implements keyword to implement an interface:

public class ClassName extends SuperclassName implements InterfaceName {
  // Class Body
}

Suppose you implement the StockOptionRecipient interface on the Manager class, as shown in Listing 1:

Listing 1. Implementing an interface
public class Manager extends Employee implements StockOptionRecipient {
  public Manager() {
  }
  public void processStockOptions (int numberOfOptions, BigDecimal price) {
    log.info("I can't believe I got " + number + " options at $" +
    price.toPlainString() + "!"); 
  }
}

When you implement the interface, you provide behavior for the method or methods on the interface. You must implement the methods with signatures that match the ones on the interface, with the addition of the public access modifier.

An abstract class can declare that it implements a particular interface, but you're not required to implement all of the methods on that interface. Abstract classes aren't required to provide implementations for all of the methods they claim to implement. However, the first concrete class (that is, the first one that can be instantiated) must implement all methods that the hierarchy doesn't implement.

Note: Subclasses of a concrete class that implements an interface do not need to provide their own implementation of that interface (because the methods on the interface have been implemented by the superclass).

Generating interfaces in Eclipse

Eclipse can easily generate the correct method signature for you if you decide that one of your classes should implement an interface. Just change the class signature to implement the interface. Eclipse puts a red squiggly line under the class, flagging it to be in error because the class doesn't provide the methods on the interface. Click the class name, press Ctrl + 1, and Eclipse suggests "quick fixes" for you. Of these, choose Add Unimplemented Methods, and Eclipse generates the methods for you, placing them at the bottom of the source file.

Using interfaces

An interface defines a new reference data type, which you can use to refer to an interface anywhere you would refer to a class. This ability includes when you declare a reference variable, or cast from one type to another, as shown in Listing 2.

Listing 2. Assigning a new Manager instance to a StockOptionEligible reference
package com.makotojava.intro;
import java.math.BigDecimal;
import org.junit.Test;
public class ManagerTest {
  @Test
  public void testCalculateAndAwardStockOptions() {
    StockOptionEligible soe = new Manager();// perfectly valid
    calculateAndAwardStockOptions(soe);
    calculateAndAwardStockOptions(new Manager());// works too
    }
    public static void calculateAndAwardStockOptions(StockOptionEligible soe) {
    BigDecimal reallyCheapPrice = BigDecimal.valueOf(0.01);
    int numberOfOptions = 10000;
    soe.awardStockOptions(numberOfOptions, reallyCheapPrice);
  }
}

As you can see, it's valid to assign a new Manager instance to a StockOptionEligible reference, and to pass a new Manager instance to a method that expects a StockOptionEligible reference.

Assignments: Interfaces

You can assign a reference from a class that implements an interface to a variable of an interface type, but certain rules apply. From Listing 2, you can see that assigning a Manager instance to a StockOptionEligible variable reference is valid. The reason is that the Manager class implements that interface. However, the following assignment would not be valid:

 Manager m = new Manager();
  StockOptionEligible soe = m; //okay
  Employee e = soe; // Wrong!

Because Employee is a supertype of Manager, this code might at first seem okay, but it's not. Why not? Because Manager implements the StockOptionEligible interface, whereas Employee does not.

Assignments such as these follow the rules of assignment that you saw in Unit 16: Inheritance. And as with classes, you can only assign an interface reference to a variable of the same type or a superinterface type.

For further exploration

Is there more to an interface than having the correct methods

Java - Interfaces

The Java Tutorials: Interfaces

IBM Code: Java journeys

Previous: InheritanceNext: Nested classes


Downloadable resources


Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java development
ArticleID=1036635
ArticleTitle=Unit 17: Interfaces
publish-date=09142016