Win a copy of Functional Reactive Programming this week in the Other Languages forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Method Overloading Question

 
Dpk
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Few days back, I saw a posting in "javacert", i am still unable to understand the error, Can anybody help me in this ?
The following code (B.java) gives Compile error:
class A {
public void test(B b) {
System.out.println("A - public void test(B b)");
}
}
class B extends A {
public void test(A a)
{
System.out.println("B - public void test(A )");
}

public static void main(String[] args) {
B b = new B();
b.test(b);
}
}
The error is : Ambigious Call at b.test(b)
I thought this may be because of Polymorphism as B is subclass of A. So compiler is unable to decide between test(B b) and test (A a). But when i copied this method in class B also:
public void test(B b) {
System.out.println("A - public void test(B b)");
}
It compiled successfully.
Any inputs on this behaviour are appreciated ! TnX !
 
Thandapani Saravanan
Ranch Hand
Posts: 117
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
At compile time the Compiler needs to know which method is referred in a method invocation expression. In this code, the method invocation expression b.test(b) is ambiguous to the compiler. The compiler is not sure whether you are referring to test in A or B. This is because the compiler thinks that the parameter to test() could be A or B.
To make it clear, we can say b.test((A)b) if we want to call B's test() or say ((A)b).test(b) if we want to call A's test().
[This message has been edited by Thandapani Saravanan (edited February 13, 2000).]
 
Anonymous
Ranch Hand
Posts: 18944
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
To my knowledge, to give polymorphism behavour, overriding methods must be same in return type, name and parameter list(order and type). Since both the test methods had different arguement types, this is not overriding behaviour.
Now B b = new B();
In this case, the contents of the pointer is object B, so it will call test(B b) of class B.
Dynamic binding is always according to the contents of the reference variable not the type of reference variable.
 
Dpk
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thandapani, I agree, but if i am having test(B b) in class B also, compiler just do fine !!! Do not need any cast !
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Neetagupta is correct that the method profiles are different, and therefore overriding and polymorphism are irrelevant to this problem. It's about overloading - the compiler needs to be able to choose which of the overloaded method signatures is more appropriate to use. This is covered in detail in the Java Language Specification here. Basically the compiler tries to determine if one method profile is more specific than the others, and if so, that's the one to use. One method declaration is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time type error. In this case:
(assume a and b are instances of classes A and B respectively.)
"a.test(b)" could be handled by A.test(B) but not by B.test(A), so A.test(B) is not more specific than B.test(A).
"b.test(a)" could not be handled by A.test(B), but it could be B.test(A), so B.test(A) is not more specific than A.test(B).
Since neither method is more specific than the other, any invocation that could apply to both (i.e. "b.test(b)") is ambiguous, and causes an error.
If you also supply a B.test(B), then this new profile is more specific than the others, and any invocation that applies to B.test(B) (as well as the others) will indeed call B.test(B) without ambiguity.
 
Dpk
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Is it not overloading case, when b (class B type) is having test(B b) from class A, and also having same name method test(A a) of it's own ? Shouldn't rule of more specific apply here ? Why it gives Ambigious error ?
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dpk: yes, this is overloading, as I said. The rule about using the most specific method does apply here. The problem is that neither method is more specific than the other. Think of it this way: If there were a method A.test(A), that would be the least specific. If there is a method B.test(B), that's the most specific (the method invocation is "b.test(b)"). Both A.test(B) and B.test(A) are in the middle, and neither one is more specific than the other, so the compiler cannot choose.
 
Dpk
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jim:
Here Class B extends A.
so test(B b)(inherited from A) and test(A a) are both methods available to any object of type B ! So if i say b.test(b) Shouldn't test(B b) be the most specific and test(A a) the least?
thanks for your Patience !
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But because test(B) is not defined in class B, it can never be considered more specific than another method that is defined in class B. That's just the way the rules are written (again, you can read them here). To summarize them another way: for a method to be more spcific than another method, it must (a) be defined in the same class or a subclass of the class that the second method is defined in, and (b) each of its arguments must be the same as the corresponding argument in the second method, or a subclass of it.
I used notation like A.test(B) as shorthand for "test(B) method defined in A" - sorry if I didn't make that clear.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic