Intro to interfaces

  • Recall:

    • A superclass defines common behavior for related subclasses.

  • Unrelated classes can also exhibit common behaviors

    Example:   compareTo( )

    • We can rank/sort numbers by their magnitude
    • We can rank/sort circles by their radius
    • We can rank/sort people by the height
    • Etc, etc

  • Interface :

    • An interface can be used to define common behavior for any classes (including unrelated classes)

Example of common behavior in non-related object types

  • Consider two unrelated classes (= object types) that we have studied before:

    public class BankAccount
    {
        private double balance;
    
        public BankAccount(double x)
        {
            balance = x;
        }
    
        public double getBalance()
        {
            return balance;
        }
    
        ...
    }  
    public class Circle extends GeometricObject
    {
        private double radius;
    
        Circle(double r)
        {
            radius = r;
        }
    
        public double getArea()
        {
            return 3.14159*radius*radius;
        }
    
        ....
    } 

  • Although BankAccount and Circle objects are unrelated, they can be compared:

    • 2 BankAccount objects can be compared with each other by their balance
    • 2 Circle objects can be compared with each other by their area

Example of common behavior in non-related object types

  • The common behavior in these 2 classes can be expressed by defining the compareTo( ) method in both classes:

    public class BankAccount
    {
        private double balance;
    
        public BankAccount(double x)
        {
            balance = x;
        }
    
        public double getBalance()
        {
            return balance;
        }
    
        public int compareTo( BankAccount other )
        {
            double diff = this.getBalance()
                          - other.getBalance();
            return (int) Math.signum(diff);
        }
        ...
    }  
    public class Circle extends GeometricObject
    {
        private double radius;
    
        Circle(double r)
        {
            radius = r;
        }
    
        public double getArea()
        {
            return 3.14159*radius*radius;
        }
    
        public int compareTo( Circle other )
        {
            double diff = this.getArea()
                          - other.getArea();
            return (int) Math.signum(diff);
        }
        ....
    } 

  • Note:   Math.signum(neg) = -1,   Math.signum(0) = 0   and   Math.signum(pos) = 1,

Review: the selection sort algorithm for Circles

We have previously studied the Selection Sort algorithm that the use < operator to compare objects:

    public static void selectionSort(Circle[] list) 
    {
        for (int i = 0; i < list.length-1; i++)
        {
            /* -----------------------------------------------
               Find the minimum in the list[i..list.length-1]
               ----------------------------------------------- */
           Circle min = list[i];     // Assume first element is min
           int minIndex        = i;           // Index where min is found

           for ( int k = minIndex+1; k < list.length; k++ )
               if ( list[k].getArea() < min.getArea() ) // Compare the area 
               {  
                   min      = list[k]; // Update min value
                   minIndex = k;       // Update its index
               }

            /* ------------------------------------------------------
               Swap list[i] with list[minIndex] if necessary
               ------------------------------------------------------ */
            if ( minIndex != i )
            {   // Swap list[minIndex] and list[i]
                Circle help = list[minIndex];  // Standard exchange alg
                list[minIndex]       = list[i];
                list[i]              = help;
            }
        }
    } 

The selection sort algorithm for Circles using compareTo()

We can re-write the Selection Sort algorithm to use the compareTo( ) method to compare objects:

    public static void selectionSort(Circle[] list) 
    {
        for (int i = 0; i < list.length-1; i++)
        {
            /* -----------------------------------------------
               Find the minimum in the list[i..list.length-1]
               ----------------------------------------------- */
           Circle min = list[i];     // Assume first element is min
           int minIndex        = i;           // Index where min is found

           for ( int k = minIndex+1; k < list.length; k++ )
               if ( list[k].compareTo(min) < 0 )        // Compare the area 
               {  
                   min      = list[k]; // Update min value
                   minIndex = k;       // Update its index
               }

            /* ------------------------------------------------------
               Swap list[i] with list[minIndex] if necessary
               ------------------------------------------------------ */
            if ( minIndex != i )
            {   // Swap list[minIndex] and list[i]
                Circle help = list[minIndex];  // Standard exchange alg
                list[minIndex]       = list[i];
                list[i]              = help;
            }
        }
    } 

Test program for selection sort algorithm for Circle objects

  • Test program for selection sort using Circle objects:

        public static void main(String[] args)
        {
             Circle[] myList = new Circle[4];
             
             myList[0] = new Circle("red", 4);
             myList[1] = new Circle("blue", 3);
             myList[2] = new Circle("grey", 5);
             myList[3] = new Circle("green", 2);
             
             for ( int i = 0; i < myList.length; i++ )
                 System.out.print( myList[i].getBalance() + " ");
    	 System.out.println();
    
             selectionSort(myList);
    
             for ( int i = 0; i < myList.length; i++ )
                 System.out.print( myList[i].getBalance() + " ");
    	 System.out.println();
        } 

DEMO: demo/05-interfaces/20-sort-bankAccount/Demo.java

Test program for selection sort algorithm for Circle objects

  • However: this selectionSort() method does not work for BankAccount objects (wrong:

        public static void main(String[] args)
        {
             BankAccount[] myList = new BankAccount[4];
             
             myList[0] = new BankAccount(400);
             myList[1] = new BankAccount(300);
             myList[2] = new BankAccount(500);
             myList[3] = new BankAccount(200);
             
             for ( int i = 0; i < myList.length; i++ )
                 System.out.print( myList[i].getBalance() + " ");
    	 System.out.println();
    
             selectionSort(myList);
    
             for ( int i = 0; i < myList.length; i++ )
                 System.out.print( myList[i].getBalance() + " ");
    	 System.out.println();
        } 

DEMO: demo/05-interfaces/20-sort-bankAccount/Demo2.java

The selection sort algorithm for BankAccount objects

In order to sort BankAcoount object, we must write the following selectionSort( ) method:

    public static void selectionSort(BankAccount[] list) 
    {
        for (int i = 0; i < list.length-1; i++)
        {
            /* -----------------------------------------------
               Find the minimum in the list[i..list.length-1]
               ----------------------------------------------- */
           BankAccount min = list[i];     // Assume first element is min
           int minIndex        = i;           // Index where min is found

           for ( int k = minIndex+1; k < list.length; k++ )
               if ( list[k].compareTo(min) < 0 ) // compare list[k] and min
               { 
                   min      = list[k]; // Update min value
                   minIndex = k;       // Update its index
               }

            /* ------------------------------------------------------
               Swap list[i] with list[minIndex] if necessary
               ------------------------------------------------------ */
            if ( minIndex != i )
            {   // Swap list[minIndex] and list[i]
                BankAccount help = list[minIndex];  // Standard exchange alg
                list[minIndex]       = list[i];
                list[i]              = help;
            }
        }
    }

DEMO: demo/05-interfaces/20-sort-bankAccount/Demo3.java

$64,000 question: can we "combine" the selectionSort( ) methods using polymorphism ?

 

  • Can we find a superclass for Circle and BankAccount ???

  • If so, we can use polymorphism (just like Circle and Rectangle)

A selection sort algorithm for both Circle and BankAccount objects

Idea for writing a selection sort algorithm for the superclass of BankAccount and Circle:

    public static void selectionSort(SuperClass[] list) 
    {
        for (int i = 0; i < list.length-1; i++)
        {
            /* -----------------------------------------------
               Find the minimum in the list[i..list.length-1]
               ----------------------------------------------- */
           SuperClass min    = list[i];           // Assume first element is min
           int minIndex  = i;                 // Index where min is found

           for ( int k = minIndex+1; k < list.length; k++ )
               if ( list[k].compareTo(min) < 0 ) // compare list[k] and min
               { 
                   min      = list[k]; // Update min value
                   minIndex = k;       // Update its index
               }

            /* ------------------------------------------------------
               Swap list[i] with list[minIndex] if necessary
               ------------------------------------------------------ */
            if ( minIndex != i )
            {   // Swap list[minIndex] and list[i]
                SuperClass help    = list[minIndex];     // Standard exchange alg
                list[minIndex] = list[i];
                list[i]        = help;
            }
        }
    }

Is there a superclass for BankAccount and Circle ???

  • Problem:   BankAccount objects and Circle objects are completely different:

  • The only thing a BankAccount object and a Circle object have in common is the compareTo( ) method !!



  • Java's solution:

      • Interface = a similar mechanism as inheritance for unrelated class that share some (a few) behavior(s) (= method(s))

Interface:   mechanism to group unrelated classes that have some common behavior

  • BankAccount objects and Circle objects behaves like "Comparable-Thing"s:

  • Interface:

      • Interface = an abstract class-like construct that contains only (1) method declarations and (2) constants (= static and final)

      • You can define interface variables but cannot instantiate objects with an interface (just like an abstract class)

Defining an interface

  • How to define an interface: (it's similar to an abstract class)

    public interface myInterface
    {
        public abstract void myMethod1( ); // abstract is optional 
        public          int myMethod2(int); 
        ... // Other methods
    }

  • An interface cannot have a constructor method

  • You can define variables of an interface type: (it's similar to an abstract class)

        myInterface a;

  • You cannot create objects of an interface type: (it's similar to an abstract class)

     Illegal:  new myInterface() 

Implementing an interface

  • Suppose we have defined the following interface:

    public interface myInterface
    {
        public void myMethod( ); // Must override to implement
    } 

  • How to implement an interface: (it's similar to a extending a class)

    public class myClass implements myInterface
    {
        // You must override all methods declared in the interface 
        public void myMethod( )
        {
            System.out.println("Success !");
        }
    } 

  • Rule:   the implementation class must override all methods declared in an interface

How to use an interface --- example

  • Because an interface is like an abstract class, you cannot instantiate an interface object

  • We always upcast an object of its implementation class and assign it to an interface variable:

    public class myProg
    {
        public static void main(String[] args)
        {
    	// This is upcasting (myInterface = "superclass")
            myInterface b = new myClass();  // Upcasting !
            ^^^^^^^^^^^^^   ^^^^^^^^^^^^^^
            Interface var   Upcast object of its implementation class
    
            b.myMethod();
        }
    }

    Note:   we can upcast an object if the class implements the interface

    I.e.: an interface is a superclass (of unrelated objects) !

DEMO: 05-interfaces/21-interface
Next:   we will define the ComparableThing interface for the BankAccount amd Circle classes

Defining and using the ComparableThing interface

  • How to define the ComparableThing interface:

    public interface ComparableThing
    {
        public int compareTo( ComparableThing x );
    }
    

  • You can define variables with the interface type:

     ComparableThing a;

  • You cannot create objects with the interface type:

     Illegal:  new ComparableThing() 

We can now write the selectionSort( ) for ComparableThing "objects"

The selection sort algorithm for ComparableThing type

We can write the selection sort algorithm to sort an array of ComparableThing as follows:

    public static void selectionSort(ComparableThing[] list) 
    {
        for (int i = 0; i < list.length-1; i++)
        {
            /* -----------------------------------------------
               Find the minimum in the list[i..list.length-1]
               ----------------------------------------------- */
           ComparableThing min = list[i];           // Assume first element is min
           int minIndex        = i;                 // Index where min is found

           for ( int k = minIndex+1; k < list.length; k++ )
               if ( list[k].compareTo(min) < 0 ) // compare list[k] and min
               { 
                   min      = list[k]; // Update min value
                   minIndex = k;       // Update its index
               }

            /* ------------------------------------------------------
               Swap list[i] with list[minIndex] if necessary
               ------------------------------------------------------ */
            if ( minIndex != i )
            {   // Swap list[minIndex] and list[i]
                ComparableThing help = list[minIndex];     // Standard exchange alg
                list[minIndex]       = list[i];
                list[i]              = help;
            }
        }
    }

Implementing the ComparableThing interface for the BankAccount class   --- Tricky !

  • Because we have defined the ComparableThing interface as:

    public interface ComparableThing
    {
        public int compareTo( ComparableThing x );
    }                         ^^^^^^^^^^^^^^^

  • We must override the method compareTo( ) as follows:

    public class BankAccount implements ComparableThing
    {
        ... 
        // You must override method with the same signature ! 
        public int compareTo( ComparableThing x )
        {
          Note:  x  is actually a BankAccount object !
        }
    } 

    Note:   a BankAccount object can be passed to compareTo( ) with upcasting !

Implementing the ComparableThing interface for the BankAccount class

The original BankAccount class that do not implement the ComparableThing interface was:

public class BankAccount
{
    private double balance;

    public BankAccount(double x)
    {
        balance = x;
    }

    public double getBalance()
    {
        return balance;
    }

    // compareTo( ) used to compare 2 BankAccount objects

    public int compareTo( BankAccount other )
    {


        double diff = this.getBalance() − other.getBalance();
        return (int) Math.signum(diff);
    }
} 

 

Implementing the ComparableThing interface for the BankAccount class

We change the BankAccount class to implement the ComparableThing interface:

public class BankAccount implements ComparableThing
{
    private double balance;

    public BankAccount(double x)
    {
        balance = x;
    }

    public double getBalance()
    {
        return balance;
    }

    // We must override compareTo( ) using same signature in ComparableThing

    public int compareTo( ComparableThing other )
    {


        double diff = this.getBalance() − other.getBalance();  // Error !
        return (int) Math.signum(diff);
    }
} 

We have an error because the ComparableThing type does not have a getBalance( ) method...

Implementing the ComparableThing interface for the BankAccount class

Solution:   we downcast the reference to BankAccount type so we can use the getBalance( ) method:

public class BankAccount implements ComparableThing
{
    private double balance;

    public BankAccount(double x)
    {
        balance = x;
    }

    public double getBalance()
    {
        return balance;
    }

    // We must override compareTo( ) using same signature in ComparableThing

    public int compareTo( ComparableThing other )
    {   
        BankAccount help = (BankAccount) other;

        double diff = this.getBalance() − help.getBalance();  // No error !
        return (int) Math.signum(diff);
    }
} 

Test program for selection sort algorithm for BankAccount objects

  • We can sort BankAccount objects using the selectionSort for ComparableThing:

        public static void main(String[] args)
        {
             BankAccount[] myList = new BankAccount[4];
             
             myList[0] = new BankAccount(400);
             myList[1] = new BankAccount(300);
             myList[2] = new BankAccount(500);
             myList[3] = new BankAccount(200);
             
             for ( int i = 0; i < myList.length; i++ )
                 System.out.print( myList[i].getBalance() + " ");
    	 System.out.println();
    
             selectionSort( myList );  // Uses upcasting !
    
             for ( int i = 0; i < myList.length; i++ )
                 System.out.print( myList[i].getBalance() + " ");
    	 System.out.println();
        }
      

DEMO: demo/05-interfaces/22-interface/Demo.java
The selectionSort() method will also work for Circle objects if Circle implements ComparableThing (next)

Implementing the ComparableThing interface for the Circle class

The original Circle class that do not implement the ComparableThing interface:

public class Circle extends GeometricObject
{
    private double radius;

    Circle(double r)
    {
        radius = r;
    }

    public double getArea()
    {
        return 3.14159*radius*radius;
    }

    // compareTo( ) used to compare 2 Circle objects

    public int compareTo( Circle other )
    {


        double diff = this.getArea() − other.getArea();
        return (int) Math.signum(diff);
    }
}

 

Implementing the ComparableThing interface for the Circle class

We change the Circle class to implement the ComparableThing interface:

public class Circle extends GeometricObject implements ComparableThing
{
    private double radius;

    Circle(double r)
    {
        radius = r;
    }

    public double getArea()
    {
        return 3.14159*radius*radius;
    }

    // We must override compareTo( ) using same signature in ComparableThing

    public int compareTo( ComparableThing other )
    {


        double diff = this.getArea() − other.getArea();  // Error !
        return (int) Math.signum(diff);
    }
} 

We have an error because the ComparableThing type does not have a getArea( ) method...

Implementing the ComparableThing interface for the Circle class

Solution:   we downcast the reference to Circle type so we can use the getArea( ) method:

public class Circle extends GeometricObject implements ComparableThing
{
    private double radius;

    Circle(double r)
    {
        radius = r;
    }

    public double getArea()
    {
        return 3.14159*radius*radius;
    }

    // We must override compareTo( ) using same signature in ComparableThing

    public int compareTo( ComparableThing other )
    {
        Circle help = (Circle) other;

        double diff = this.getArea() − help.getArea();   // No error !
        return (int) Math.signum(diff);
    }
} 

Test program for selection sort algorithm for Circle objects

  • We can sort Circle objects using the selectionSort for ComparableThing:

        public static void main(String[] args)
        {
             Circle[] myList = new Circle[4];
             
             myList[0] = new Circle("red", 4);
             myList[1] = new Circle("green", 3);
             myList[2] = new Circle("blue", 5);
             myList[3] = new Circle("yellow", 2);
             
             for ( int i = 0; i < myList.length; i++ )
                 System.out.print( myList[i].getRadius() + " ");
    	 System.out.println();
    
             selectionSort( myList );  // Uses upcasting !
    
             for ( int i = 0; i < myList.length; i++ )
                 System.out.print( myList[i].getRadius() + " ");
    	 System.out.println();
        }
      

The selectionSort() method will work for any class that implements the ComparableThing interface !!

Additional information on interfaces

  • A class can inherit (= extends) from only one class

    But: a class can implement multiple interfaces

    Example:

       public class MyApp extends App
                          implements ActionListener, KeyListener
       {
          ...    
       }

  • Important result:

    • Each interface defines a set of capabilities or "roles"

    • Implementing an interface allows a class to fulfill the role defined by an interface

    • Therefore:   a class in Java can fulfill multiple roles !

Additional information on interfaces

  • instanceof:

    • The instanceof operator tells you whether a variable "is a" member of a class or an interface

      (I.e.: an interface is similar to a (abstract) class in Java !)

  • Examples:

       Circle a      = new Circle("red", 2);
       BankAccount b = new BankAccount(100);
    
       a instanceof ComparableThing    ---> true
       a instanceof ComparableThing    ---> true
    

Quiz on instanceof

  • Suppose the class Dog is defined as:

         class Dog extends Animal implements Pet
         {
            ...
         }
    
         Dog fido = new Dog();

    What is the outcome of the following instanceof expressions:

     fido instanceof Dog
     fido instanceof Animal    
     fido instanceof Pet       
     fido instanceof Object  

Quiz on instanceof

  • Suppose the class Dog is defined as:

         class Dog extends Animal implements Pet
         {
            ...
         }
    
         Dog fido = new Dog();

    Answers: all are true...

     fido instanceof Dog      true (self)
     fido instanceof Animal   true (superclass)
     fido instanceof Pet      true (interface is like superclass)
     fido instanceof Object   true (super-superclass)

A scenario for default implementation of methods in an interface

  • You write a super cool interface.

    You provide your interface to a bunch of friends and they implement your interface with various super cool classes and deploy their code on their super cool websites....

  • Later....

    You realize you forgot to add one of your desired methods to your interface.

  • You edit your interface to add this abstract method....

    Result:

    • All of your friends' super cool classes won't compile because they haven't implemented this new method, and their websites are unusable.

Methods with a default implementation in an interface

  • You can define methods with a "default" implementation in an interface

  • Syntax to declare (abstract) methods with a default implementation:

       public interface InterfaceName
       {
           public default returnType methodName( params )
           {
               default method body
           }
       }

  • Usage:

    • When the implementing class does not override a method with a default implementation:

      • The Java compiler will use the default implementation as the overriding method

DEMO: demo/05-interfaces/30-default-impl/Demo.java + Demo2.java

Additional information on interfaces   --- interface inheritance

  • An interface can extend one or more interfaces

    Example:

       public interface Insurable extends Sellable, Transportable
       {
           public int insuredValue();
       }

    The interface Insurable will combine:

    • All methods in Sellable
    • All methods in Transportable
    • The insuredValue() method

  • Note:

    • Unlike classes that can extend only 1 class, interfaces can extend more than 1 interface

Comparing an abstract class vs an interface

 

Abstract class Interface
  • Can have constructors, instance variables, non-abstract methods
  • Can only have abstract methods and constants
  • Is extended by a subclass that may implement the abstract methods, but does not have to.

    (If the subclass does not implement all abstract methods, it must be defined as an abstract class too)

  • Is implemented by a subclass that must implement all the abstract methods

Postscript

  • Remember the ComparableThing interface that we studied in these slides:

    public interface ComparableThing
    {
        public int compareTo( ComparableThing x );
    }

  • I took it from the Java library:

         Interface Comparable<T>  

  • I also simplified it by removing the "generic type" <T> to make the examples understandable at your current level

    (We will study "generics" later in the course....)