• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Jeanne Boyarsky
  • Ron McLeod
Sheriffs:
  • Paul Clapham
  • Liutauras Vilda
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
Bartenders:

Overloading across classes

 
Ranch Hand
Posts: 2596
Android Firefox Browser Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
Consider this from JLS
8.4.7 Overloading
If two methods of a class (whether both declared in the same class, or both inherited by a class, or one declared and one inherited) have the same name but different signatures, then the method name is said to be overloaded. This fact causes no difficulty and never of itself results in a compile-time error. There is no required relationship between the return types or between the throws clauses of two methods with the same name but different signatures.
Methods are overridden on a signature-by-signature basis.
If, for example, a class declares two public methods with the same name, and a subclass overrides one of them, the subclass still inherits the other method. In this respect, the Java programming language differs from C++.
[c++ is pretty clear on this, there's no overloading across classes unless you explicitly do it using "using ..." construct.]
NOW -
<code><pre>
public class A
{
public static void main(String[] args)
{
D obj = new D();
int i = 100;
double d = 100.1;
char c = 'M';
obj.m1(c);
obj.m1(i); //ERROR!!!
obj.m1(d);
}
}
class D extends B
{
public char m1(char c)
{
System.out.println("derived char " + c + " " +c);
return c;
}
public double m1(double d)
{
System.out.println("derived double " + (d + 1.1));
return d + 1.1;
}
}
class B
{
public int m1(int i)
{
System.out.println("base int " + (i + 1));
return i + 1;
}
}
</pre>
</code>
This gives comile time error, which says -
<code><pre>
Reference to m1 is ambiguous. It is defined in double m1(double) and int m1(int).
obj.m1(i);
^
1 error
</pre>
</code>
I have following questions -
(1) In class D, all three methods are accessible, while resolving the ambiguous call "obj.m1(i);", the most specific method (as per JLS) should be - public int m1(int i) which is both applicable and accesible, no promotion whatsoever is needed. So why ambiguity???
(2) There are two very interesting observations here -
Case 1 :
If I override the method "public int m1(int i)" in class D(with or w/o changing the implementation), the thing comiles smooth and (understandably) invokes class D method.
NOW, since "public int m1(int i)" is very much accessible (and also applicable) in class D, why should this make any difference?
If I do not override it in class D, the base class implementation should prevail.
Case 2 :
More interestingly, if I just comment method "public double m1(double d)" in class D, and calls to that method, it compiles and overloading is smooth across classes, ensuring that class B method is accessible, aplicable and hence used.
In presence of "public double m1(double d)" however things change, a method call "obj.m1(i);" is ambiguos. My question obviously is "WHY?". If it is due to promotion rule then I again have 2 doubts -
(a) When there is most specific method available for int argument - public int m1(int i) - in class D's scope, that's whwre the call should be resolved by the compiler, without any need of considering promotion.
(b)Again, even char can be promoted if needed, it is not an argument like bolean which is type incompatiable. Despite of this, a call to a method "obj.m1(c);" is resolved to the most specific case w/o any compile error.
So why a call to "obj.m1(i);", is not resolved to its most specific case which is both accessible and applicable. What am I missing? Where am I incorrect and/or inaccurate in my assumptions/understanding?
Could somebody pl. explain this in details?
TIA,
- Manish
[This message has been edited by Manish Hatwalne (edited October 01, 2001).]
 
Greenhorn
Posts: 14
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Manish,
I had asked a similar question which was clarified at great length by Jose Botella. Here are the details:
_________________________________________________________________
We have to consider both the list of arguments and the class where the methods were declared:
A method is more specific than other if it was declared in a class that is the same or a subclass of the other, and if each of its arguments have the same type or can be converted by a widenning conversion to the corresponding types of the other method.
_________________________________________________________________
As per this, let us see in your case:
Is the first method declared in D more specific than the one declared in B? It could be because D extends B, but it isn't because double can't be converted to int via a widening conversion.
Is the method declared in B more specific than the one declared in D? It isn't because B can't be converted to D via a widening conversion, although its argument type int can be promoted to double.
So none is more specific tham the other and the ambigous error is produced.
Read JLS 15.12.2.1 for more on the subject.
HIH
Raj shah
 
Manish Hatwalne
Ranch Hand
Posts: 2596
Android Firefox Browser Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanx Raj,
I managed to find a similar thread at Sun's Java site.
Overloading ambiguity
Guess, should have looked here first . My mistake!!!
Interestingly, if I change the order (ie. double method in Base "B" class, and more specific int method in Derived "D" class) it works fine.
I should have thought abt. class widening as well...
Anyway, now it's clearer. (though I believe c++ way is much better, IMHO)
Thanks again,
- Manish
[This message has been edited by Manish Hatwalne (edited October 01, 2001).]
 
Manish Hatwalne
Ranch Hand
Posts: 2596
Android Firefox Browser Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Actually, since JLS clears it in the topic - how to resolve such calls in details, in a somewhat complex (but precise) language, it does justify the compiler error. However, I think (and still believe) that this is somewhat incorrect/inappropriate (for lack of better words) behaviour of the Java compiler. I mean, if both the methods are accessible and applicable, choosing more specific method should not depend upon the class to which it belongs, the most specific method should be chosen by the compiler, i.e. in the above case it should have been "an int for an int". . My curiosity got better of me and I looked for ppl. who thought liewise on Sun's Java site, and indeed, I found this reported as a bug by many ppl. Of course, Sun begs to differ and stick to their JLS way for compiler implementation. Does anybody here know why it is not possible for Java compiler to choose such method, irrespective of its class (as C++ compiler can do this)?
Is there a chance that it might get considered in the future versions of Java, just like there is a good chance that Java 1.5 *might* support covariant return type, and operator overloading isn't far away. Does anybody know something abt. this one?
Here is the listed bug (among many similar ones listed), and Sun's resolution - Closed, not a bug. (I usually love this resolution though )
http://developer.java.sun.com/developer/bugParade/bugs/4038412.html
More here -
Bugs related to overloadiing ambiguity
HTH,
- Manish
[This message has been edited by Manish Hatwalne (edited October 06, 2001).]
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic