Constants in Interfaces

A field declaration in an interface defines a named constant. Naming conventions recommend using uppercase letters, with multiple words in the name being separated by underscores. Such constants are considered to be public, static, and final. These modifiers are usually omitted from the declaration, but can be specified in any order. Such a constant must be initialized with an initializer expression.

An interface constant can be accessed by any client (a class or interface) using its qualified name, regardless of whether the client extends or implements its interface. However, if the client is a class that implements this interface or is an interface that extends this interface, then the client can also access such constants directly by their simple names. Such a client inherits the interface constants. Typical usage of constants in interfaces is illustrated in Example 5.16, showing access both by the constant’s simple name and its qualified name in the print statements at (1) and (2), respectively.

Example 5.16 Constants in Interfaces

Click here to view code image

// File: Client.java
interface Constants {
  double PI_APPROXIMATION = 3.14;
  String AREA_UNITS       = “sq.cm.”;
  String LENGTH_UNITS     = “cm.”;
}
//______________________________________________________________________________
public class Client implements Constants {
  public static void main(String[] args) {
    double radius = 1.5;
    // (1) Using simple name:
    System.out.printf(“Area of circle is %.2f %s%n”,
               PI_APPROXIMATION * radius*radius, AREA_UNITS);
    // (2) Using qualified name:
    System.out.printf(“Circumference of circle is %.2f %s%n”,
             2.0 * Constants.PI_APPROXIMATION * radius, Constants.LENGTH_UNITS);
  }
}

Output from the program:

Click here to view code image

Area of circle is 7.06 sq.cm.
Circumference of circle is 9.42 cm.

Extending an interface that has constants is analogous to extending a class that has static variables. This is illustrated in Figure 5.5 and Example 5.17. Note the diamond shape of the inheritance hierarchy, indicating the presence of multiple inheritance paths through which constants can be inherited. The constants IDLE and BUSY at (1) and (2) in the interface IBaseStates are inherited by the subinterface IAllStates via both the interface IExtStatesA and the interface IExtStatesB. In such cases, the constant is considered to be inherited only once and can be accessed by its simple name, as shown at (12) in Example 5.17.

Figure 5.5 Inheritance Relationships for Interface Constants

Constants can be hidden by the subinterfaces. The declaration of the constant BLOCKED at (6) in the interface IAllStates hides the declaration of the constant at (2) in the interface IBaseStates. The new declaration can be accessed by its simple name in a class implementing the interface IAllStates, as shown at (10) in Example 5.17. The hidden constant declaration can always be accessed by using its qualified name as shown at (11) in Example 5.17.

In the case of multiple inheritance of interface constants, any name conflicts can be resolved by using the qualified name to access the constants. This is illustrated by the constant DISMANTLED, which is declared in both the IExtStatesA and IExtStatesB interfaces. Both declarations are inherited by the subinterface IAllStates. Such declarations are said to be ambiguous. The compiler will report an error only if such constants are accessed by their simple names, as shown at (7) and (8) for the constant DISMANTLED. Only the qualified name can be used to disambiguate such constants and resolve the conflict, as shown at (7a) and (8a) for the constant DISMANTLED.

When defining a set of related constants, the recommended practice is to use an enum type, rather than named constants in an interface.

Example 5.17 Inheriting Constants in Interfaces

Click here to view code image

// File: Factory.java
import static java.lang.System.out;

interface IBaseStates {
  String IDLE = “idle”;                                // (1)
  String BUSY = “busy”;                                // (2)
  String BLOCKED = “blocked”;                          // (3)
}
//_______________________________________________________________________________
interface IExtStatesA extends IBaseStates {
  String DISMANTLED = “dismantled”;                    // (4)
}
//_______________________________________________________________________________
interface IExtStatesB extends IBaseStates {
  String DISMANTLED = “kaput”;                         // (5)
}
//_______________________________________________________________________________
interface IAllStates extends IExtStatesB, IExtStatesA {
  String BLOCKED = “out of order”;                     // (6) hides (3)
//String OBSOLETE = BLOCKED + “, ” +
//                  DISMANTLED + ” and scrapped.”;     // (7) Ambiguous
  String OBSOLETE = BLOCKED + “, ” +
         IExtStatesB.DISMANTLED + ” and scrapped”;     // (7a)
}
//_______________________________________________________________________________
public class Factory implements IAllStates {
  public static void main(String[] args) {
//  out.println(“Machine A is ” + DISMANTLED);             // (8) Ambiguous.
    out.println(“Machine A is ” + IExtStatesB.DISMANTLED); // (8a)
    out.println(“Machine B is ” + OBSOLETE);           // (9) IAllStates.OBSOLETE
    out.println(“Machine C is ” + BLOCKED);            // (10) IAllStates.BLOCKED
    out.println(“Machine D is ” + IBaseStates.BLOCKED);// (11)
    out.println(“Machine E is ” + BUSY);               // (12) Simple name
  }
}

Output from the program:

Click here to view code image

Machine A is kaput
Machine B is out of order, kaput and scrapped
Machine C is out of order
Machine D is blocked
Machine E is busy


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *