Java: overload methods

I wonder why the call

zf(-6); 

in class M refers to the following function in class B:

 public void f(double y) { this.x = (int) y + By; } 

instead of using the function f in class A, since bx is covered by A. Or rather, it uses

 public void f (int y) { this.x = y*2; By = this.x; } 

in class B, where at least the parameter type matches.

Full 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 + By); } } 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; By = this.x; } public void f(double y) { this.x = (int) y + By; } } public class M { public static void main (String[] args){ A a = new A(By); af(1); B b = new B(3.0); A z = b; zf(-5.0); zf(-6); System.out.println(bx + " " + zx); } } 
+4
source share
4 answers
 zf(-6); 

The static type z is A , which has only one method named f . This method accepts the double parameter, which can be promoted with a literal value of -6 . Therefore, during compilation, the call is bound to Af(double) .

When starting z a type of type B found that overrides Af(double) with its own Bf(double) , and therefore this method calls.

+3
source

The static type of z is A , so zf(-6) can only bind to a method in A , which in this case is Af(int) .

The language is designed so that

 A z = new B(3.0); zf(-6); 

will always behave the same way

 A z = complicatedWayToComputeTrue() ? new B(3.0) : new A(3.0); zf(-6); 

If the compiler had to bind to a different method signature because it can prove that A z always contains B , then this will lead to all kinds of non-local effects for the language, which makes it very difficult to debug or support java.

Imagine someone trying to support

 final A z = complicatedWayToComputeTrue() ? new B(3.0) : new A(3.0); // 1000 lines elided zf(-6); 

changing it to

 A z = new B(3.0); // 1000 lines elided zf(-6); 

If the compiler can now prove that A always B and binds Zf to the method in B , the maintainer will be puzzled.

+3
source

Java is a separate dispatch, while you are trying to do a double dispatch (where the method invoked depends on both the dynamic execution class and the parameters).

The method signature for the call in Java is determined at compile time; this means that the declared class of the object determines which method is bound. Overriding a method in a subclass affects the associated implementation, but the method is not overloaded (because the overloaded method has a different signature).

In class B, you overload f () with the version that accepts int, when using an object declared as a class of class A, this method does not exist (you cannot call it, and it will not be called).

Summarizing:

  • The compiler is bound to the method signature at compile time.
  • This related signature depends on the declared (compilation time) object and parameters.
  • If a method is overridden in a subclass, then when called in a subclass (regardless of the type declared), an overridden method will be selected.
  • Overloading does not redefine, for redefinition you need the same method signature (well, except for covariance).
+1
source

Well, maybe I'm wrong, but if you linked an object z type A to an object of type B , it would still be attached as type B , so it executes the method in class B , not class A Note that you are NOT creating an object of type A , since you are not using new .

And as Mike Samuel said, by default -6 should be considered as int , but that doesn't match your explanation. I will try to find the right answer for this.

0
source

Source: https://habr.com/ru/post/1401270/


All Articles