Reputation: 5
i've been struggling to understand some piece of code of java that uses inheritance to calculate the output. The code is the following:
class A
{
public int calc(double num) {
System.out.println("calc de A");
return (int)(num+1);
}
}
class B extends A
{
public int calc(long num) {
System.out.println("calc de B");
return (int)(num+2);
}
}
class C extends B
{
public int calc(int num) {
System.out.println("calc de C");
return num+3;
}
}
class D extends C
{
public int calc(float num) {
System.out.println("calc de D");
return (int)(num+4);
}
}
class Main
{
public static void main(String[] args)
{
int num1 = 10;
long num2 = num1;
A a1 = new D();
A a2 = new D();
int result = a1.calc(num1) + a2.calc(num2);
System.out.println("Numero: "+ result);
}
}
Me and my friends think the output of the console should be:
calc de C
calc de B
Numero: 25
But we run it in Eclipse and in Ideone (link: http://ideone.com/CTdklv) to test it and the answer given is
calc de A
calc de A
Numero: 22
Can someone explain why does the output is 22 if the signatures of the methods are different.
We belive that if you call the calc method using and int as the parameter you should go to the calc method of the B class instead of the A class.
I appreceate your help! Thanks.
Upvotes: 0
Views: 106
Reputation: 37855
In Java, which overloads can be called is determined by the type of the reference variable (15.12.1):
If the form (of the method invocation expression) is ExpressionName . [TypeArguments] Identifier, then the class or interface to search is the declared type T of the variable denoted by ExpressionName if T is a class or interface type, or the upper bound of T if T is a type variable.
Since a1
and a2
are declared to be A
, you can assign a D
to them but you can only call the method from A
.
You can see that it works this way if you change the types around a little bit:
class A {
void m(int i) {}
}
class B extends A {
void m(double d) {}
}
A a = new B();
double d = 0d;
a.m(d); // won't compile
// will say something like
// 'double can not be converted to int'
So if you change a1
and a2
to D
D a1 = new D();
D a2 = new D();
the output should be as you expected because the overloads in B
, C
and D
are available to call.
Note that it works this way for overrides as well.
class A {
protected void m() {}
}
class B extends A {
@Override
public void m() {}
}
// in another package...
B b = new B();
b.m(); // call m because it is public in B
A a = b;
a.m(); // won't compile because it is protected in A
Which methods are available is determined by the type of the reference.
Upvotes: 1