Reputation: 163
I am wondering why the call of
z.f(-6);
in class M refers to the following function in class B:
public void f(double y) {
this.x = (int) y + B.y;
}
instead of using function f in class A, since b.x is covered by A. Or rather uses
public void f (int y) {
this.x = y*2;
B.y = this.x;
}
in class B where at least the parameter type matches.
Complete Code below:
public class A {
public int x = 1;
public A(int x) {
this.x += x;
}
public A (double x) {
x += x;
}
public void f(double x) {
this.x = this.x + (int) (x + B.y);
}
}
public class B extends A {
public static int y = 3;
public int x = 0;
public B (double x) {
super((int) x);
}
public void f(int y) {
this.x = y*2;
B.y = this.x;
}
public void f(double y) {
this.x = (int) y + B.y;
}
}
public class M {
public static void main (String[] args){
A a = new A(B.y);
a.f(1);
B b = new B(3.0);
A z = b;
z.f(-5.0);
z.f(-6);
System.out.println(b.x + " " + z.x);
}
}
Upvotes: 4
Views: 438
Reputation: 7232
Java is single dispatch, whereas what you are attempting to do is double dispatch (where the method invoked depends on both the dynamic runtime class and parameters).
The signature of a method to invoke in Java is determined at compile time; this means that the declared class of the object determines which method is bound to. Overriding a method in a subclass affects the bound implementation, but overloading a method does not (since the overloaded method has a different signature).
In class B you are overloading f() with a version that takes an int, when using an object declared as being of class A, this method does not appear to exist (you cannot call it, and it will not be invoked).
To summarize:
Upvotes: 1
Reputation: 53
Well I might be wrong, but if you link the object z
of type A
to an object of type B
, it will still bind as type B
, that's why it's executing the method in class B
and not in class A
. Note that you are NOT creating an object of type A
since you're not using new
.
And as Mike Samuel said, by default -6
should be considered an int
, but that doesn't fit with your explanation. I'll try to find out a proper answer for this.
Upvotes: 0
Reputation: 28752
z.f(-6);
Static type of z
is A
, which has only one method named f
. That method takes double
parameter, to which the literal value -6
can be promoted. So at compile time the call is bound to A.f(double)
.
At runtime z
is found to be of type B
, which overrides A.f(double)
with its own B.f(double)
, and so that this the method that gets called.
Upvotes: 3
Reputation: 120486
The static type of z
is A
so z.f(-6)
can only bind to a method in A
, which in this case is A.f(int)
.
The language is designed this way so that
A z = new B(3.0);
z.f(-6);
will always behave the same as
A z = complicatedWayToComputeTrue() ? new B(3.0) : new A(3.0);
z.f(-6);
If the compiler were to bind to a different method signature because it can prove that A z
always holds a B
then this would introduce all kinds of non-local effects to the language making it really hard to debug or maintain java programs.
Imagine someone trying to maintain
final A z = complicatedWayToComputeTrue() ? new B(3.0) : new A(3.0);
// 1000 lines elided
z.f(-6);
by changing it to
A z = new B(3.0);
// 1000 lines elided
z.f(-6);
If the compiler can now prove that A
is always a B
and binds Z.f
to a method in B
, the maintainer will be baffled.
Upvotes: 3