The Interface mechanism to group non-similar object types

  • Consider two unrelated types of classes (= object types) than 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 not related, 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

The Interface mechanism to group non-similar object types

  • To compare the objects, we define a compareTo( ) method in each of the 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);
        }
        ....
    } 

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

The selection sort algorithm for BankAccount objects

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

    public static void selectionSort(BankAccount[] list) 
    {
        for (int i = 0; i < list.length - 1; i++) 
	{
            int minIndex = findSmallest(list, i );

	    if ( minIndex != i ) 
	    {   // Swap list[minIndex] and list[i]
	        BankAccount help = list[minIndex];
                list[minIndex] = list[i];
		list[i] = help;
            }
        }
    }

public static int findSmallest(BankAccount[] myList, int start) { BankAccount min; // smallest value in array int indexOfMin; // index where the smallest value is found // Find min value and its index min = myList[start]; // Assume first element is min indexOfMin = start; for ( int i = start+1; i < myList.length; i++ ) if ( myList[i].compareTo(min) < 0 ) // Found a larger element { min = myList[i]; // Update min value indexOfMin = i; } return indexOfMin; }

Test program for selection sort algorithm for BankAccount objects

  • Test program for selection sort using BankAccount objects:

        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();
        }
      

However: this selectionSort() method does not work for Circle objects

The selection sort algorithm for Circle objects

We will need to write a separate selection sort algorithm to sort an array of Circle:

    public static void selectionSort(Circle[] list) 
    {
        for (int i = 0; i < list.length - 1; i++) 
	{
            int minIndex = findSmallest(list, i );

	    if ( minIndex != i ) 
	    {   // Swap list[minIndex] and list[i]
	        Circle help = list[minIndex];
                list[minIndex] = list[i];
		list[i] = help;
            }
        }
    }

public static int findSmallest(Circle[] myList, int start) { Circle min; // smallest value in array int indexOfMin; // index where the smallest value is found // Find min value and its index min = myList[start]; // Assume first element is min indexOfMin = start; for ( int i = start+1; i < myList.length; i++ ) if ( myList[i].compareTo(min) < 0 ) // Found a larger element { min = myList[i]; // Update min value indexOfMin = i; } return indexOfMin; }

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(4);
             myList[1] = new Circle(3);
             myList[2] = new Circle(5);
             myList[3] = new Circle(2);
             
             for ( int i = 0; i < myList.length; i++ )
                 System.out.print( myList[i].getArea() + " ");
    	 System.out.println();
    
             selectionSort(myList);
    
             for ( int i = 0; i < myList.length; i++ )
                 System.out.print( myList[i].getArea() + " ");
    	 System.out.println();
        }
      

It would be nice if we can use the same selectionSort( ) method to sort both kind of objects !!!

The selection sort algorithm for Circle and Rectangle objects

Idea:   write 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++) 
	{
            int minIndex = findSmallest(list, i );

	    if ( minIndex != i ) 
	    {   // Swap list[minIndex] and list[i]
	        SuperClass help = list[minIndex];
                list[minIndex] = list[i];
		list[i] = help;
            }
        }
    }

public static int findSmallest(SuperClass[] myList, int start) { SuperClass min; // smallest value in array int indexOfMin; // index where the smallest value is found // Find min value and its index min = myList[start]; // Assume first element is min indexOfMin = start; for ( int i = start+1; i < myList.length; i++ ) if ( myList[i].compareTo(min) < 0 ) // Found a larger element { min = myList[i]; // Update min value indexOfMin = i; } return indexOfMin; }

Is there a superclass for BankAccount and Circle ???

  • Problem:   BankAccount objects and Circle objects are completely different from one another:

  • 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 classes that have some common behavior

  • BankAccount objects and Circle objects have a common behavior: the compareTo() method:

  • Interface:

      • Interface = a class-like construct that contains only (1) abstract methods and (2) constants (rarely)

      • A class that implements an interface must define (= override) all the abstract methods in the interface

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
    }

  • 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 in the interface 
        public void myMethod( )
        {
            System.out.println("Success !");
        }
    } 

Test program for Interface example

  • Test program for the interface example:

    public class myProg
    {
        public static void main(String[] args)
        {
            // (1) Normal way of using objects
            myClass a = new myClass();
            a.myMethod();
    
    	// (2) Using an interface (= "superclass") variable
            myInterface b = new myClass();  // Upcasting !
            b.myMethod();
        }
    }

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

    I.e.: a interface is juts like a superclass

We will write the ComparableThing interface for the BankAccount amd Circle classes next

Defining 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() 

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++) 
	{
            int minIndex = findSmallest(list, i );

	    if ( minIndex != i ) 
	    {   // Swap list[minIndex] and list[i]
	        ComparableThing help = list[minIndex];
                list[minIndex] = list[i];
		list[i] = help;
            }
        }
    }

public static int findSmallest(ComparableThing[] myList, int start) { ComparableThing min; // smallest value in array int indexOfMin; // index where the smallest value is found // Find min value and its index min = myList[start]; // Assume first element is min indexOfMin = start; for ( int i = start+1; i < myList.length; i++ ) if ( myList[i].compareTo(min) < 0 ) // Found a larger element { min = myList[i]; // Update min value indexOfMin = i; } return indexOfMin; }

Implementing the ComparableThing interface for the BankAccount class

  • 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:

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();
        }
      

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].getArea() + " ");
    	 System.out.println();
    
             selectionSort( myList );  // Uses upcasting !
    
             for ( int i = 0; i < myList.length; i++ )
                 System.out.print( myList[i].getArea() + " ");
    	 System.out.println();
        }
      

The selectionSort() method will also work for Circle objects if Circle implements ComparableThing (next)