Review:   superclass parameters can make a method more general  

We can use the following selectionSort() method to sort arrays of any subclass of GeometricObject:

 public static void selectionSort(GeometricObject[] list) // Can sort any subclass 
 {
     for (int i = 0; i < list.length-1; i++)
     {
         /* -----------------------------------------------
            Find the minimum in the list[i..list.length-1]
            ----------------------------------------------- */
        GeometricObject 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() ) // Sort objects based by 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]
             GeometricObject help = list[minIndex];  // Standard exchange alg
             list[minIndex] = list[i];
             list[i]        = help;
         }
     }
 } 

Intro to interfaces

  • The problem with inheritance (= making subclasses):

    • A superclass contains the common behavior(s) of related subclasses

    • Inheritance can be applied only when the subclass is related to its superclass


  • 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

      Yet, numbers, circles and people are completely unrelated objects...

  • 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 the following unrelated classes:   (1) BankAccount that contains balance of a bank account
                                                                            (2) Circle that contains radius of a circle

    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

Example of common behavior in non-related object types

  • A BankAccount can be compared with another BankAccount based on their balance
    A Circle can be compared with another Circle based on their area

    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. value) = -1,   Math.signum(0) = 0   and   Math.signum(pos. value) = 1

Review: the selection sort algorithm for Circles

We have previously studied the Selection Sort algorithm that uses the  <  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 2 circles 
               {  
                   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 2 circles 
               {  
                   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

What happens when we use selectionSort(Circle[]) to sort an array of BankAccount objects ?

  • The selectionSort(Circle[]) method does not work for 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();
        } 

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

The selection sort algorithm for Circles

The Selection Sort method that sort Circle objects must use parameter type Circle[] or a superclass type:

    public static void selectionSort(Circle[] or superclass-of-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 )   // <--- Compares the 2 Circles 
               {  
                   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 BankAccount objects

On the other hand:   the Selection Sort method that sort BankAccount objects must use:

    public static void selectionSort(BankAccount[] or superclass-of-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 )   // <--- Compares the 2 BankAccounts 
               { 
                   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

A selection sort algorithm for both Circle and BankAccount objects

We could write a selection sort method for both of BankAccount and Circle using their SuperClass:

    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 ) // <-- Compares the 2 SuperClass objects
               { 
                   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;
            }
        }
    }

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

 

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

    •  If  we can find a superclass for Circle and BankAccount, we can apply polymorphism and write selectionSort() for both data types

      (Just like what we did with Circle and Rectangle)

Is there a superclass for BankAccount and Circle ???

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

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



  • Java's solution:

      • Interface = a similar mechanism like inheritance but designed 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 and using an interface

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

    public interface myInterfaceName
    {
       public static final PI = 3.1415;     // Constant(s)
       public abstract void myMethod1( );   // Abstract method(s)
       public          int  myMethod2(int); // Keyword abstract is optional
       ... 
    
       // No constructors allowed
    }

  • An interface cannot have any constructor methods

    I.e.:   you cannot create objects of an interface type:

     new myInterfaceName()   // is illegal 

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

     myInterface a;      // is legal

Implementing (= inheriting from) an interface

  • Suppose we have defined the following interface:

    public interface myInterface   // An interface is an abstract class
    {
        public void myMethod( );   // Must be overridden to be useful
    } 

  • A class "implements" an interface if the class overrides all methods in an interface:

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

  • Furthermore:

    • The implementation class is a subclass of the 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

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

  • The ComparableThing interface contains the common action(s) (= method(s)) in Circle and BankAccount:

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


  • We can define variables with the interface type:

     ComparableThing a;

  • We 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
    {
        ... 
        // We 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);
    }
} 

Therefore:   we cannot pass an array of BankAccount to selectionSort(ComparableThing[] list),

Implementing the ComparableThing interface for the BankAccount class

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

    because BankAccount implements (= is a subclass of) ComparableThing

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

Therefore:   we cannot pass an array of Circle to selectionSort(ComparableThing[] list),

Implementing the ComparableThing interface for the Circle class

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

DEMO: demo/05-interfaces/22-interface/Demo.java
The selectionSort() method will work for any class that implements the ComparableThing interface !!