9
class One { 
  public void doThing(One o) {System.out.println("One");}
}

class Two extends One{
  public void doThing(Two t) {System.out.println("Two");}
}

public class Ugly {
  public static void main(String[] args) {
    Two t = new Two();
    One o = t;
    o.doThing(new Two());
  }
}

Result : One

class One { 
  public void doThing(One o) {System.out.println("One");}
}

class Two extends One{
  public void doThing(Two t) {System.out.println("Two");}
}

public class Ugly {
  public static void main(String[] args) {
    Two t = new Two();
    One o = t;
    t.doThing(new Two());
  }
}

Result : Two

I know that at runtime, even though the object reference is of the super class type, the actual object type will be known and the actual object's method will be called. But if that is the case, then on runtime the doThing(Two t) method should be called but instead the super class method doThing(One o) is called. I would be glad if somebody explained it

In the second piece of code it prints "Two".

Question : when calling from the super class reference it is calling the doThing(One o) when calling from the sub class reference it is calling the doThing(Two o)

NOTE: I know that i am over loading and not over riding. i have edited my question for better clarity.

Thirumalai Parthasarathi
  • 4,541
  • 1
  • 25
  • 43

5 Answers5

12

The method doThing() have different method signature in One and Two.

One.doThing(One one)
Two.doThing(Two two)

Since, the signature isn't matched, Two.doThing(Two) doesn't Override One.doThing(One) and since o is of type One, One.doThing() is called.

Also to be noted that One.doThing(One) can take instance of Two as an argument for One.doThing(One) as Two extends One.

Basically, "@nachokk - You are Overloading, not Overriding"

In first scenario, when you did

Two t = new Two();
One o = t;
o.doThing(new Two());

So, o is an instance of One and Two.doThing(Two) isn't available to o thus calls One.doThing(One)

In second scenario,

Two t = new Two();
One o = t;
t.doThing(new Two());

t is an instance of Two and thus Two.doThing(Two) is called.

TheKojuEffect
  • 20,103
  • 19
  • 89
  • 125
1

You are just overloading,as you said

    Two t = new Two();
    One o = t;
    o.doThing(new Two());

Even though the actual object at runtime is a Two object and not a One object, the choice of which overloaded method to call (in other words, the signature of the method) is NOT dynamically decided at runtime. Just remember, the reference type (not the object type) determines which overloaded method is invoked!

When you call doThing() method with Two object argument,you will invoke One super class doThing() method.The doThing() method needs a One object, and Two IS-A One. So, in this case, the compiler widens the Two reference to a One object, and the invocation succeeds. The key point here is that reference widening depends on inheritance, in other words the IS-A test.

  • so are you saying that even though the object that is invoking the method is of type `Two` the method that will be chosen and bound by the reference that calls it? – Thirumalai Parthasarathi Sep 19 '13 at 12:52
1

The excelent book SCJP for Java 6 states:

If a method is overridden but you use a polymorphic (supertype) reference to refer to the subtype object with the overriding method, the compiler assumes you’re calling the supertype version of the method.

So basically with using supertype for reference you're telling compiler to use supertype method.

Matej
  • 7,728
  • 4
  • 23
  • 30
  • i don't get this.. the method is not overriding. Could you give me an example of what you are saying with code? – nachokk Sep 19 '13 at 13:27
0

This is something trick question
Your statment
One o = t;
I think , you are assuming that class One 'o' is equal to Class Two 't', which is not actually equal to class Two 't'
as Class Two 't' is inherited from Class One, so it will assign the base class One in your case,
So variable 't' is reference of the class One and hence will call the method of class One.
More over you create one more class named as ClassC class and try to set your statement
ClassC c= new ClassC ()
and then
One o = c;
You will get an error... hope the answer your question.

RAS
  • 8,100
  • 16
  • 64
  • 86
Ahmad
  • 13
  • 1
  • 5
-1

At the compile time the compiler searches the class One for the method doThing(Two t) but since there isn't a method with that signature it starts widening its search and finds doThing(One o). Then it holds the binary file with the descriptor one parameter whose type is One : void. At runtime since the object invoking the method is of type Two, in class Two it looks for the method that matches the descriptor and doesn't search for the method doThing that accepts an object of Two as it considers the descriptor in the binary file it links the call to the method doThing(One o).

the java specs was of great help explaining this. here is the link

Thirumalai Parthasarathi
  • 4,541
  • 1
  • 25
  • 43