Monday, February 7, 2011

Overloading Vs Overriding



OVERLOADING



Invoking Overloaded Methods 
Any Class can have more than one methods with the same name but with different argument lists, which means the method is overloaded.
Deciding which of the matching methods to invoke is based on the arguments. If you invoke the method with a String argument, the overloaded version that takes a String is called. If you invoke a method of the same name but pass it a float, the overloaded version that takes a float will run.
If you invoke the method of the same name but pass it a Foo object, and there isn't an overloaded version that takes a Foo, then the compiler will complain that it can't find a match.
  class Adder {
            public int addThem(int x, int y) {
                  return x + y;
            }

            // Overload the addThem method to add doubles instead of ints
            public double addThem(double x, double y) {
                  return x + y;
            }
      }

      // From another class, invoke the addThem() method
public class TestAdder {

      public static void main(String[] args) {
            Adder a = new Adder();

            int b = 27;
            int c = 3;
            int result = a.addThem(b, c); // Which addThem is invoked?
            double doubleResult = a.addThem(22.5, 9.3);

            }


The following are examples of invoking overloaded methods:
In the preceding TestAdder code, the first call to a.addThem(b,c) passes two ints to the method, so the first version of addThem()—the overloaded version that takes two int arguments—is called.
The second call to a.addThem(22.5, 9.3) passes two doubles to the method, so the second version of addThem()—the overloaded version that takes two double arguments—is called.

Important Funda:

Invoking overloaded methods that take object references rather than primitives is a little more interesting.
Say you have an overloaded method such that one version takes an Animal and one takes a Horse (subclass of Animal).
If you pass a Horse object in the method invocation, you'll invoke the overloaded version that takes a Horse. Or so it looks at first glance:




      class Animal {
      }

      class Horse extends Animal {
      }

      class UseAnimals {
            public void doStuff(Animal a) {
                  System.out.println("In the Animal version");
            }
            public void doStuff(Horse h) {
                  System.out.println("In the Horse version");
            }

            public static void main(String[] args) {
                  UseAnimals ua = new UseAnimals();
                  Animal animalObj = new Animal();
                  Horse horseObj = new Horse();
                  ua.doStuff(animalObj);
                  ua.doStuff(horseObj);
            }
      }


The output is what you expect:
In the Animal version
In the Horse version
But what if you use an Animal reference to a Horse object?
Animal animalRefToHorse = new Horse();
ua.doStuff(animalRefToHorse);
 Which of the overloaded versions is invoked?
You might want to say, "The one that takes a Horse, since It's a Horse object at runtime that's being passed to the method." But that's not how it works.
The preceding code would actually print: In the Animal version
Even though the actual object at runtime is a Horse and not an Animal, the choice of which overloaded method to call (in other words, the signature of the (method) is NOT dynamically decided at runtime).
To summarize, which overridden version of the method to call is decided at runtime based on object type, but which overloaded version of the method to call is based on the reference type of the argument passed at compile time.
If you invoke a method passing it an Animal reference to a Horse object, the compiler knows only about the Animal, so it chooses the overloaded version of the method that takes an Animal. It does not matter that at runtime there's actually a Horse being passed.


OVERRIDING


Polymorphism in Overloaded and Overridden Methods


How does polymorphism work with overloaded methods? From what we just looked at, it doesn't appear that polymorphism matters when a method is overloaded.

If you pass an Animal reference, the overloaded method that takes an Animal will be invoked, even if the actual object passed is a Horse.

Once the Horse masquerading as Animal gets in to the method, however, the Horse object is still a Horse despite being passed into a method expecting an Animal.

So it's true that polymorphism doesn't determine which overloaded version is called; polymorphism does come into play when the decision is about which overridden version of a method is called.

But sometimes, a method is both overloaded and overridden. Imagine the Animal and Horse classes look like this:

     public class Animal {
            public void eat() {
                  System.out.println("Generic Animal Eating Generically");
            }
      }

      public class Horse extends Animal {
            public void eat() {
                  System.out.println("Horse eating hay ");
            }

            public void eat(String s) {
                  System.out.println("Horse eating " + s);
            }
      }


Notice that the Horse class has both overloaded and overridden the eat() method.

Table shows which version of the three eat() methods will run depending on how they are invoked.


Method Invocation Code
Result
Animal a = new Animal();
a.eat();
Generic Animal Eating Generically
Horse h = new Horse();
h.eat();
Horse eating hay
Animal ah = new Horse();
ah.eat();
Horse eating hay Polymorphism works—the actual object type (Horse), not the reference type (Animal), is used to determine which eat() is called.
Horse he = new Horse();
he.eat("Apples");
Horse eating Apples
The overloaded eat (String s) method is invoked.
Animal a2 = new Animal();
a2.eat("treats");
Compiler error! Compiler sees that Animal class doesn't have an eat() method that takes a String.
Animal ah2 = new Horse();
ah2.eat("Carrots");
Compiler error! Compiler still looks only at the reference, and sees that Animal doesn’t have an eat() method that takes a String. Compiler doesn’t care that the actual object might be a Horse at
runtime.


4 comments:

  1. Quite Innovative.
    Could you please write on database connectivity in jsp too.

    ReplyDelete
  2. Very helpful post.

    It would be great if you can share your thoughts on usage of Abstract Class and interface.
    When and why?

    ReplyDelete
  3. Will be coming up with that tooo....

    ReplyDelete
  4. Nice tutorial, overloading and overriding is always confusing to each other. By the way I have also blogged about What is Polymorphism in Java , let me know how do you find it.

    ReplyDelete