| As discussed earlier, Java does not allow a class to inherit more 
              than one class as in C++. That is,   class 
              Test extends aClass, bClass{ // Error !! There are situations where multiple inheritance can be useful but 
              it can also lead to problems. For example, a reference to a method 
              with the same name in both classes needs a system for making it 
              explicit as to which class should be used. Iinterfaces provide most of the advantages of multiple inheritance 
              with fewer problems. An interface is basically an abstract 
              class but with all 
              of the methods abstract. (The methods in an 
              interface do not need the explicit abstract 
              modifier since they are abstract by definition.) A class implements 
              an interface rather than extends it. Any class that implements 
              the interface must override all the interface methods with it's 
              own methods. (In the case of identical method names in two interfaces, it's 
              irrelevant since both methods are abstract and carry no code body. 
              In a sense, both are overridden by the single method of that name 
              in the implementing class.) In the example below, Runnable 
              is an interface with a single method: run(). 
              So any method that implements Runnable 
              must override run(). 
              
              
                 
                  | class 
                      Test extends Applet implements 
                      Runnable{
 ...
 public 
                      void 
                      run 
                      () {
 ...
 }
 }
 interface 
                      Runnable{
 public 
                      void 
                      run 
                      ();
 }
 |  Any number of interfaces can be implemented. Just 
                separate the interface names with a comma:  
              
                 
                  | class 
                    Test extends Applet implements 
                    Runnable, 
                    AnInterface {
 ...
 public 
                    void 
                    run 
                    () {
 ...
 }
 ...
 public 
                    void 
                    walk 
                    () {
 ...
 }
 }
 
 interface 
                    AnInterface
 {
 public 
                    void 
                    walk 
                    ();
 }
 |  Any class that implements an interface can be referenced 
                as a type of that interface, as shown in this code:  
              
                 
                  | class 
                      Test extends Applet {
 public 
                      void init () {
 Runnable r;
 r = new 
                      user();
 ...
 ...
 }
 }
 
 class 
                      User implements 
                      Runnable
 {
 public 
                      void run () {
 ...
 }
 }
 |   
              Note: Interface 
                names often end with "able" 
                to imply that they add to the capabilty of the class. Interfacing Classes Interface is a very suitable name because they provide a systematic 
              way of providing an entrance to a class. That is, they provide a 
              common interface.  Suppose we have classes Relay 
              and Valve 
              that are completely independent, perhaps written by two different 
              people. If we want he class Test 
              to communicate with these classes, an interface provides a simple, 
              standard way to do this.  Lets define an interface called Switchable, 
              which holds a single method called getState(), 
              as in 
 public 
              interface Switchable
 {
 public boolean getState();
 }
 We want to use getState() 
              to return a value that indicates whether a relay or a valve is on 
              or off. In the code below we show the class Test 
              that casts instances of Relay and Valve as Switchable 
              types and it can then call their respective getState() 
              to communicate with them:   
              
                 
                  | public 
                      class 
                      Test{
 public static void 
                      main(String [] args)
 {
 Switchable 
                      [] state = new Switchable[2];
 state[0] = new Relay ();
 state[1] = new Valve ();
 
 for (int 
                      i=0; i < 2; i++)
 {
 if 
                      (state[i].getState ()) sum++;
 }
 }
 ... other code ...
 }
 
 class 
                      Relay implements Switchable
 {
 boolean setting = false;
 // 
                      Override the interface method
 boolean 
                      getState ()
 {
 return 
                      setting;
 }
 ... 
                      other code ...
 }
 class 
                      Valve implements Switchable{
 boolean open = false;
 // 
                      Override the interface method
 boolean 
                      getState 
                      ()
 {
 return 
                      open;
 }
 ... 
                      other code ...
 }
 interface 
                      Switchable{
 void 
                      getState ();
 }
 |  So the only modifications required for the classes 
                Relay 
                and Valve 
                were the implementation of the interface Switchable. 
                We override the getState() 
                with code appropriate to the task for the particular class.  In the class Test 
              we illustrate how we can treat instances of Relay 
              and Valve 
              as a common type of Switchable 
              and use the getState() 
              to find the desired info for the particular class. If later we want to find the state from a Pump 
              or other class that represents a device of interest, we just tell 
              the author to implement the Switchable 
              interface. So we see that an interface can serve literally to interface 
              otherwise incompatible classes together. Interfaces 
              for Callbacks A common technique in the C language is to pass a 
              pointer to a function in the argument list of another function. 
              The receiving function can invoke the passed function using the 
              pointer. This approach is referred to as a callback.  Callbacks are very useful in situations where you 
              want to invoke different functions without needing to know what 
              particular function is being invoked. For example, a plotting function 
              could receive a pointer to a function that takes a value on the 
              horizontal axis as an argument and returns a value for the vertical 
              axis. The plotting function could then plot any such function that 
              is passed to it.   Java, however, does not provide for pointers (direct 
              memory addresses) to methods. Instead, interfaces are used for callbacks. 
              In this case, a method holds an interface reference in its argument 
              list and then invokes a method in the interface.  (The Method 
              class in the Reflection 
              package can represent a method and can invoke it in a general manner. 
              However, it is not recommended to use Method 
              for callbacks. It is rather clumsy and it also loses the type checking 
              on the arguments and return type during the compilation.) In the following code, we see that the  
              aFunc(Switchable obj) method invokes 
              the getState() 
              method of the Switchable 
              interface. An instance of any class that implements the Switchable 
              interface can be passed, thus providing the same generality as the 
              pointer callbacks in C.  
              
                 
                  | public 
                      class 
                      TestCallBack{
 public static void 
                      main(String [] args)
 {
 Switchable 
                      [] switches = new Switchable[3];
 switches[0] = new Relay 
                      ();
 switches[1] = new Relay 
                      ();
 switches[2] = new Valve 
                      ();;
 
 for 
                      (int i=0; i < 3; i++)
 {
 aFunc (switches[i]);
 }
 }
 // Pass Switchable objects 
                      and call their getState()
 void aFunc (Switchable obj)
 {
 if (obj.getState 
                      ()) doSomething ();
 }
 ... other code...
 }
 
 See previous example for the Switchable,
 Relay, & Valve definitions.
 |    More 
              about Interfaces An interface can also contain data fields but they must be declared 
              static and 
              final, where 
               final 
              indicates that the data cannot be modified. (See Chapter 
              5: Interfaces with Only Constants.) An interface can extend another interface and thus inherit the 
              abstract methods and final, static data of the super-interface. We will discuss access rules and modifiers in the next chapter 
              but here we will note that interface methods are public. 
              (So the overriding methods in the classes that implement the interface 
              must also be public.) An interface can be empty. That is, an interface could contain 
              no methods or data at all. Such an empty interface can be useful 
              as a "marker" of classes. That is, you can use the instanceof 
              operator to determine if a class is of the particular marker type, 
              which then can imply some quality of the class. We will see later, 
              for example, that one can use the empty cloneable 
              interface to indicate whether a class overrides the clone 
              method from Object 
              for making copies of the class.    Last update: Oct. 23, 2004 |