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

    I.e.: you cannot create objects of an interface type: (it's similar to an abstract class)

     Illegal:  new myInterface() 

  • You can define variables of an interface type: (to achieve polymorphism)

        myInterface a;

Implementing an interface

  • Suppose we have defined the following interface:

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

  • We implement an interface with an "implementation" class as follows:

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

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

How to use an interface --- example

  • Remember: you cannot instantiate an object with an interface type

  • 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 a = new myClass();  // Upcasting !
            ^^^^^^^^^^^^^   ^^^^^^^^^^^^^^
            Interface var   Upcast object of its implementation class
    
            a.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/Demo.java
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 !!