Overriding and Overloading

# Overriding and Overloading
## ■Overriding
`Overriding` is a feature that allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its super-classes or parent classes. 

~~~Superclass.java
class SuperClass {
    public void methodA(int i) {
        // calculate a + b   
    }
}
~~~

~~~SubClass.java
class SubClass {
    @Override
    public void methodA(int i) {
        // calculate a + b
        // output the result of a + b
    }
}
~~~

### Rules for method overriding
####１. **Overriding and Access-Modifiers**
The access modifier for an overriding method can allow more, but not less, access than the overridden method.

~~~Parent.java
class Parent
{
    // private methods are not overridden
    private void m1() { System.out.println("From parent m1()");}
     
    protected void m2() { System.out.println("From parent m2()"); }
}
~~~

~~~ Child.java
class Child extends Parent
{
    // new m1() method
    // unique to Child class
    private void m1() { System.out.println("From child m1()");}
     
    // overriding method
    // with more accessibility
    @Override
    public void m2() { System.out.println("From child m2()");}
     
}
~~~

~~~Main.java
class Main
{
    public static void main(String[] args)
    {
        Parent obj1 = new Parent();
        obj1.m2();
        Parent obj2 = new Child();
        obj2.m2();
    }
}
~~~

~~~Output.md
From parent m2()
From child m2()
~~~

####２. **Final methods can not be overridden**
If we don’t want a method to be overridden, we declare it as final.

~~~Parent.java
    // can't be overridden
    final void show();
~~~

~~~Child.java
class Child extends Parent
{
    // This would produce error
    void show() {  }
}
~~~

~~~Output.md
error: show() in Child cannot override show() in Parent
    void show() {  }
         ^
  overridden method is final
~~~

####３.**Static methods can not be overridden(Method Overriding vs Method Hiding)**
When you defines a static method with same signature as a static method in base class, it is known as `method hiding`.
The following table summarizes what happens when you define a method with the same signature as a method in a super-class.

||SUPERCLASS INSTANCE METHOD|SUPERCLASS STATIC METHOD|
|:-------:|:-------:|:-------:|
|**SUBCLASS INSTANCE METHOD**|Overrides|Generates a compile-time error|
|**SUBCLASS STATIC METHOD**|Generates a compile-time error|Hides|

~~~Parent.java
class Parent
{
    // Static method in base class which will be hidden in subclass 
    static void m1() { System.out.println("From parent static m1()");}
     
    // Non-static method which will be overridden in derived class 
    void m2() { System.out.println("From parent non-static(instance) m2()"); }
}
~~~

~~~Child.java
class Child extends Parent
{
    // This method hides m1() in Parent
    static void m1() { System.out.println("From child static m1()");}
     
    // This method overrides m2() in Parent 
    @Override
    public void m2() { System.out.println("From child non-static(instance) m2()");}
     
}
~~~

~~~Main.java
class Main
{
    public static void main(String[] args)
    {
        Parent obj1 = new Child();
         
        // As per overriding rules this should call to class Child static 
        // overridden method. Since static method can not be overridden, it 
        // calls Parent's m1() 
        obj1.m1(); 
     
        // Here overriding works and Child's m2() is called 
        obj1.m2(); 
    }
}
~~~

~~~Output.md
From parent static m1()
From child non-static(instance) m2()
~~~

####４.**Private methods can not be overridden**

####５.**The overriding method must have same return type (or subtype)**

####６.**Invoking overridden method from sub-class**
We can call parent class method in overriding method using `super` keyword.

~~~Parent.java
// base class
class Parent
{
    void show() {
        System.out.println("Parent's show()");
    }
}
~~~

~~~Child.java
// inherited class
class Child extends Parent
{
    // This method overrides show() of Parent
    @Override
    void show() {
        super.show();
        System.out.println("Child's show()");
    }
}
~~~

~~~Main.java
class Main
{
    public static void main(String[] args) {
        Parent obj = new Child();
        obj.show();
    }
}
~~~

~~~Output.md
Parent's show()
Child's show()
~~~

####７.**Overriding and constructor **
We can not override constructor as parent and child class can never have constructor with same name(Constructor name must always be same as Class name).

####８.**Overriding and Exception-Handling**
Below are two rules to note when overriding methods related to exception-handling.

- **Rule#1**

If the super-class overridden method does not throws an exception, subclass overriding method can only throws the unchecked exception, throwing checked exception will lead to compile-time error.

~~~Parent.java
class Parent
{
    void m1() { System.out.println("From parent m1()");}
     
    void m2() { System.out.println("From parent  m2()");}
}
~~~

~~~Child.java
class Child extends Parent
{
    @Override
    // no issue while throwing unchecked exception
    void m1() throws ArithmeticException {
        System.out.println("From child m1()");
    }
     
    @Override
    // compile-time error
    // issue while throwin checked exception
    void m2() throws Exception {
        System.out.println("From child m2");
    }  
}
~~~

~~~Output.java
error: m2() in Child cannot override m2() in Parent
    void m2() throws Exception{ System.out.println("From child m2");}
         ^
  overridden method does not throw Exception
~~~

- **Rule#2**

If the super-class overridden method does throws an exception, subclass overriding method can only throw same, subclass exception. Throwing parent exception in Exception hierarchy will lead to compile time error.Also there is no issue if subclass overridden method is not throwing any exception.

~~~Parent.java
class Parent
{
    void m1() throws RuntimeException {
        System.out.println("From parent m1()");
    }
}
~~~

~~~Child1.java
class Child1 extends Parent
{
    @Override
    // no issue while throwing same exception
    void m1() throws RuntimeException { 
        System.out.println("From child1 m1()");
    }
~~~

~~~Child2.java
class Child2 extends Parent
{
    @Override
    // no issue while throwing subclass exception
    void m1() throws ArithmeticException {
        System.out.println("From child2 m1()");
    }    
}
~~~

~~~Child3.java
class Child3 extends Parent
{
    @Override
    // no issue while not throwing any exception
    void m1() {
        System.out.println("From child3 m1()");
    }    
}
~~~

~~~Child4.java
class Child4 extends Parent
{
    @Override
    // compile-time error
    // issue while throwing parent exception
    void m1() throws Exception {
        System.out.println("From child4 m1()");
    }    
}
~~~

~~~Output.md
error: m1() in Child4 cannot override m1() in Parent
    void m1() throws Exception
         ^
  overridden method does not throw Exception
~~~

####９.**Overriding and abstract method**
Abstract methods in an interface or abstract class are meant to be overridden in derived concrete classes otherwise compile-time error will be thrown.

####１０.**Overriding and synchronized/stricfp method**
The presence of synchronized/stricfp modifier with method have no effect on the rules of overriding, i.e. it’s possible that a synchronized/stricfp method can override a non synchronized/stricfp one and vice-versa.

## ■Overloading
Overloading allows different methods to have same name, but different signatures where signature can differ by number of input parameters or type of input parameters or both. Overloading is related to compile time (or static) polymorphism.

~~~Sum.java
public class Sum {
 
    // Overloaded sum(). This sum takes two int parameters
    public int sum(int x, int y) {
        return (x + y);
    }
 
    // Overloaded sum(). This sum takes three int parameters
    public int sum(int x, int y, int z) { 
         return (x + y + z);
    }
 
    // Overloaded sum(). This sum takes two double parameters
    public double sum(double x, double y) { 
         return (x + y);
    }   
 
    // Driver code
    public static void main(String args[]) { 
        Sum s = new Sum();
        System.out.println(s.sum(10, 20));
        System.out.println(s.sum(10, 20, 30));
        System.out.println(s.sum(10.5, 20.5));
    }
}
~~~

~~~Output.md
30
60
31.0
~~~

### what is the advantage?
We don’t have to create and remember different names for functions doing the same thing. For example, in our code, if overloading was not supported by Java, we would have to create method names like sum1, sum2,… or sum2Int, sum3Int, … etc.

# Reference
- [Overriding in Java](https://www.geeksforgeeks.org/overriding-in-java/)
- [Overloading in Java](https://www.geeksforgeeks.org/overloading-in-java/)