Google

Jun 3, 2014

Understanding Overriding, Hiding, and Overloading in Java? How does overriding give polymorphism?

Overriding, Hiding, and Overloading are important core Java concepts and you will be quizzed on job interviews or written tests.

What is overriding?

An instance method overrides all accessible instance methods with the same signature in super classes. If overriding were not possible, you can't have the OO concept  known as polymorphism. Let's explain this with a simple example.


Q.  Can you tell what will be the output of the following code snippet?

public class Base {
 public void f() {
  System.out.println("Base");
 }
}

public class DerivedOne extends Base{
 
 @Override //ensures signature is the same at compile-time
 public void f() {
  System.out.println("Derived 1"); // overrides Base.f()
 }
}

public class DerivedTwo extends Base{
 
 @Override //ensures signature is the same at compile-time
 public void f() {
  System.out.println("Derived 2"); //overrides Base.f()
 }
}


Test polymorphism:

public class PolymorphismTest {
 
 public static void main(String[] args) {
  
  Base b = new DerivedOne();
  b.f();//1
  
  b = new DerivedTwo();
  b.f();//2
  
  b = new Base();
  b.f();//3
 }
}


A. The output will be

Derived 1
Derived 2
Base

What is happening here?

1. Method overriding (i.e. polymorphic behavior) is occurring at run time to determine stored object type.
2. Even though the variable "b" is of type Base, which f( ) method gets called depends on what type of object is stored in that variable. Stored variable type is immaterial.

  • //1 the stored object is of type DerivedOne, hence prints "Derived 1".
  • //2  the stored object is of type DerivedTwo, hence prints "Derived 2".
  • //3 the stored object is of type Base, hence prints "Base"

This is polymorphism. Poly in greek means many and Morph means change. So polymorphism is the ability (in programming) to present the same interface for differing underlying forms (data types).


What is hiding or shadowing?

The polymorphism and overriding are applicable only to non-static methods (i.e. instance methods). If you try to override a static method,  it is known as hiding. For example,

public class Base {
 
 int a = 5;
 
 public static void f() {
  System.out.println("Base");
 }
}


public class DerivedOne extends Base{

 int a = 7; //hides B.a
 
 public static void f() {
  System.out.println("Derived 1"); // hides Base.f()
 }
}


Test hiding:

public class PolymorphismTest {
 
 public static void main(String[] args) {
  
  Base b = new DerivedOne();
  b.f(); // prints "Base"
 
  b = new Base();
  b.f();  //prints "Base"
 }
}



Why prints "Base" in both cases? Because, it only looks at what type variable "b" is? in both cases of type Base. It does not care what type of object is stored. Same for variables, and is known as "Shadowing"

public class PolymorphismTest {
 
 public static void main(String[] args) {
  
  Base b = new DerivedOne();
  System.out.println(b.a);        //prints 5
  
  b = new DerivedTwo();
  System.out.println(b.a); //prints 5
 }

}


prints 5. So, hiding and shadowing are Bad Practices, and should be avoided.


Q. What is method overloading? Unlike, overriding and hiding that happen when you have an inheritance hierarchy like Parent, Child classes, Overloading happens within the same class.

Methods in a class overload one another if they have the same name and different signatures. Unlike overriding, overloading happens at compile time. It knows at compile time based on the method arguments you pass.

public class Base {
 
 public  void f() {
  System.out.println("Base");
 }
 
 public  void f(String a) {
  System.out.println("Base"); //overloaded
 }
 
 public  void f(int b) {
  System.out.println("Base"); // overloaded
 }
}



Finally,

Q. What is obscuring? A variable obscures a type with the same name if both are in scope. Say, your instance and local variables have the same name.

public class Base {
 
 int a = 5;
 
 public  void f() {
  int a = 7; //obscuring instance variable a
  System.out.println(a);
 } 
}



Test obscuring:

public class PolymorphismTest {
 
 public static void main(String[] args) {
  
  Base b = new DerivedOne();
  b.f(); //prints 7 -- local varible obscures instance variable
 }

}

So, overriding and overloading are good, but avoid method hiding (i.e. having same name static methods in parent/child classes), variable shadowing (i.e. having similar variable names in parent/child classes), and variable obscuring (i.e. having same variable name for instance, static, and local variables).

Labels:

1 Comments:

Blogger Pradip Garala said...

"hiding and shadowing" is nice topic...

3:57 PM, June 04, 2014  

Post a Comment

Subscribe to Post Comments [Atom]

<< Home