Review (background knowledge):   how Java determine which method to use

  • Java determines which method to call/use by matching the method signature :

    Example:

      public static void main(String[] args)
      {
         method(1);          // Calls method( int x )
         method(1.0);        // Calls method( double x )
         method(1, 1);       // Calls method( int x, int y )
      }
    
      public static void method( int x )
      {
         System.out.println("Running: method( int x ) ");
      }
        
      public static void method( double x )
      {
         System.out.println("Running: method( double x ) ");
      }
        
      public static void method( int x, int y )
      {
         System.out.println("Running: method( int x, int y ) ");
      }

DEMO: 13-inheritance/11-overload/Overloading.java

Overloading vs. overriding

  • Overloading = defining different methods with the same (method) name but with different (method) signatures

    Consider the class NewClass that inherits the methods method1( ) and method2( ) from SomeClass:

    public class NewClass extends SomeClass
    {
        NewClass(int a)
        {
            super(a);
        }
    
        // Inherits: method1()  and method2()               
    
        
       
           
      
    
    
       
           
    	
      
    } 
    public class SomeClass
    {
        public int x;
    
        public SomeClass(int a)
        {
            x = a;
        }
    
        public void method1( )
        {
            System.out.println("SomeClass.method1()");
        }
        
        public void method2( )
        {
            System.out.println("SomeClass.method2()");
        }
    }
     

 

Overloading vs. overriding

  • Overloading = defining different methods with the same (method) name but with different (method) signatures

    If we define the method method1(int a), it will overload method1() because their signatures are different:

    public class NewClass extends SomeClass
    {
        NewClass(int a)
        {
            super(a);
        }
    
        // Inherits: method1()  and method2()
    
        public void method1(int a) // Overloads method1()   
        {
            System.out.println("NewClass.m1(int)");
        }
    
     
       
            
    	 
       
    } 
    public class SomeClass
    {
        public int x;
    
        public SomeClass(int a)
        {
            x = a;
        }
    
        public void method1( )
        {
            System.out.println("SomeClass.method1()");
        }
        
        public void method2( )
        {
            System.out.println("SomeClass.method2()");
        }
    } 
    
    

 

Overloading vs. overriding

  • Overloading = defining different methods with the same (method) name but with different (method) signatures

    Therefore:   method1() will invoke the inherited SomeClass' method1( ) (by matching method signature):

    public class NewClass extends SomeClass
    {
        NewClass(int a)
        {
            super(a);
        }
    
        // Inherits: method1()  and method2()
    
        public void method1(int a) // Overloads method1()   
        {
            System.out.println("NewClass.m1(int)");
        }
    
        public void method3()
        {
            method1();   // Invokes SomeClass' method1()
    	
        }
    } 
    public class SomeClass
    {
        public int x;
    
        public SomeClass(int a)
        {
            x = a;
        }
    
        public void method1( )
        {
            System.out.println("SomeClass.method1()");
        }
        
        public void method2( )
        {
            System.out.println("SomeClass.method2()");
        }
    } 
    
    

 

Overloading vs. overriding

  • Overloading = defining different methods with the same (method) name but with different (method) signatures

    Therefore:   method1(22) will invoke NewClass' method1(int a) (by matching method signature):

    public class NewClass extends SomeClass
    {
        NewClass(int a)
        {
            super(a);
        }
    
        // Inherits: method1()  and method2()
    
        public void method1(int a) // Overloads method1()
        {
            System.out.println("NewClass.m1(int)");
        }
    
        public void method3()
        {
            method1();   // Invokes SomeClass' method1()
    	method1(22); // Invoked NewClass' method1(int a)
        }
    } 
    public class SomeClass
    {
        public int x;
    
        public SomeClass(int a)
        {
            x = a;
        }
    
        public void method1( )
        {
            System.out.println("SomeClass.method1()");
        }
        
        public void method2( )
        {
            System.out.println("SomeClass.method2()");
        }
    } 
    
    

DEMO: demo/13-inheritance/11-overload    (run main() and trace with BlueJ)

Overloading vs. overriding

  • Overriding = replacing an inherited method by defining a method with the same (method) signature

    Again, consider the class NewClass that inherits the methods method1( ) and method2( ) from SomeClass:

    public class NewClass extends SomeClass
    {
        NewClass(int a)
        {
            super(a);
        }
    
        // Inherits: method1()  and method2()               
    
        
       
           
      
    
    
       
           
    	
      
    } 
    public class SomeClass
    {
        public int x;
    
        public SomeClass(int a)
        {
            x = a;
        }
    
        public void method1( )
        {
            System.out.println("SomeClass.method1()");
        }
        
        public void method2( )
        {
            System.out.println("SomeClass.method2()");
        }
    }
     

 

Overloading vs. overriding

  • Overriding = replacing an inherited method by defining a method with the same (method) signature

    If we define the method method1(), it will override method1() because their signatures are the same:

    public class NewClass extends SomeClass
    {
        NewClass(int a)
        {
            super(a);
        }
    
        // Inherits: method1()  and method2()               
    
        public void method1()      // Overrides method1()
        {
            System.out.println("NewClass.m1()");
        }
       
           
       
           
    	
      
    } 
    public class SomeClass
    {
        public int x;
    
        public SomeClass(int a)
        {
            x = a;
        }
    
        public void method1( )
        {
            System.out.println("SomeClass.method1()");
        }
        
        public void method2( )
        {
            System.out.println("SomeClass.method2()");
        }
    }
     

 

Overloading vs. overriding

  • Overriding = replacing an inherited method by defining a method with the same (method) signature

    Therefore:   method1() will invoke NewClass' method1() because local methods in the same class takes priority:

    public class NewClass extends SomeClass
    {
        NewClass(int a)
        {
            super(a);
        }
    
        // Inherits: method1()  and method2()               
    
        public void method1()      // Overrides method1()
        {
            System.out.println("NewClass.m1()");
        }
       
        public void method3()
        {
            method1();       // Invokes NewClass' method1() 
    
        }         
    } 
    public class SomeClass
    {
        public int x;
    
        public SomeClass(int a)
        {
            x = a;
        }
    
        public void method1( )
        {
            System.out.println("SomeClass.method1()");
        }
        
        public void method2( )
        {
            System.out.println("SomeClass.method2()");
        }
    }
     

 

Overloading vs. overriding

  • Overriding = replacing an inherited method by defining a method with the same (method) signature

    We must use super.method1() to invoke the inherited method method1() from SomeClass:

    public class NewClass extends SomeClass
    {
        NewClass(int a)
        {
            super(a);
        }
    
        // Inherits: method1()  and method2()
    
        public void method1()      // Overrides method1()
        {
            System.out.println("NewClass.m1()");
        }
    
        public void method3()
        {
            method1();       // Invokes NewClass' method1() 
    	super.method1(); // Invokes SomeClass method1()
        }
    } 
    public class SomeClass
    {
        public int x;
    
        public SomeClass(int a)
        {
            x = a;
        }
    
        public void method1( )
        {
            System.out.println("SomeClass.method1()");
        }
        
        public void method2( )
        {
            System.out.println("SomeClass.method2()");
        }
    }  
    
    

DEMO: demo/13-inheritance/12-override    (run main() and Trace with BlueJ)

Java's compiler indication for overriding

  • You can add the override annotation @Override before an overriding method for clarity and compiler check

    The Java compiler will report an error if the defined method does not override any inherited methods:

    public class NewClass extends SomeClass
    {
        NewClass(int a)
        {
            super(a);
        }
    
        // Inherits: method1()  and method2()
        @Override
        public void method1()      // Overrides method1()
        {
            System.out.println("NewClass.m1()");
        }
    
        public void method3()
        {
            method1();       // Invokes NewClass' method1() 
    	super.method1(); // Invokes SomeClass method1()
        }
    } 
    public class SomeClass
    {
        public int x;
    
        public SomeClass(int a)
        {
            x = a;
        }
    
        public void method1( )
        {
            System.out.println("SomeClass.method1()");
        }
        
        public void method2( )
        {
            System.out.println("SomeClass.method2()");
        }
    }  
    
    

DEMO: demo/13-inheritance/12-override/ --- edit NewClass and re-compile --- also try: method1(int a) for error

Additional conditions on overriding methods

  • The overriding method must have the same return type as the overridden method

    You will get a type incompatible error when you use different return types

    public class NewClass extends SomeClass
    {
        NewClass(int a)
        {
            super(a);
        }
    
        // Overrides method1() in SomeClass 
        // must have same return type (void)
        public void method1()      // Overrides method1()
        {
            System.out.println("NewClass.m1()");
        }
    
        public void method3()
        {
            method1();       // Invokes NewClass' method1() 
    	super.method1(); // Invokes SomeClass method1()
        }
    } 
    public class SomeClass
    {
        public int x;
    
        public SomeClass(int a)
        {
            x = a;
        }
    
        public void method1( )
        {
            System.out.println("SomeClass.method1()");
        }
        
        public void method2( )
        {
            System.out.println("SomeClass.method2()");
        }
    }  
    
    

DEMO: demo/13-inheritance/12-override/ --- change type void to int in NewClass method1 and re-compile

Additional conditions on overriding methods

  • The overriding method should have the same accessibility modifier as the overridden method

    Complicated errors can result when you do not use the same accessibility...

    public class NewClass extends SomeClass
    {
        NewClass(int a)
        {
            super(a);
        }
    
        // Overrides method1() in SomeClass 
        // should use same access specifier 
        public void method1()      // Overrides method1()
        {
            System.out.println("NewClass.m1()");
        }
    
        public void method3()
        {
            method1();       // Invokes NewClass' method1() 
    	super.method1(); // Invokes SomeClass method1()
        }
    } 
    public class SomeClass
    {
        public int x;
    
        public SomeClass(int a)
        {
            x = a;
        }
    
        public void method1( )
        {
            System.out.println("SomeClass.method1()");
        }
        
        public void method2( )
        {
            System.out.println("SomeClass.method2()");
        }
    }  
    
    

DEMO: demo/13-inheritance/12-override/ --- change public to private in NewClass method1 ---> compile error