Java: методы перегрузки - PullRequest
       22

Java: методы перегрузки

4 голосов
/ 14 марта 2012

Мне интересно, почему зов

z.f(-6);

в классе M относится к следующей функции в классе B:

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

вместо использования функции f в классе A, поскольку b.x покрывается A. Или, скорее, использует

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

в классе B, где хотя бы совпадает тип параметра.

Полный код ниже:

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);
       }
  }

Ответы [ 4 ]

3 голосов
/ 14 марта 2012
z.f(-6);

Статический тип z равен A, который имеет только один метод с именем f.Этот метод принимает параметр double, к которому можно добавить буквальное значение -6.Таким образом, во время компиляции вызов связан с A.f(double).

Во время выполнения z имеет тип B, который переопределяет A.f(double) со своим собственным B.f(double), и поэтомуметод, который вызывается.

3 голосов
/ 14 марта 2012

Статический тип z равен A, поэтому z.f(-6) может связываться только с методом в A, который в данном случае равен A.f(int).

Язык разработан таким образом, чтобы

A z = new B(3.0);
z.f(-6);

всегда будет вести себя так же, как

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

Если бы компилятор связывался с другой сигнатурой метода, потому что он может доказать, что A z всегда содержит B, то это привнесло бы в язык все виды нелокальных эффектов, затрудняя его отладку или поддержку Java-программы.

Представьте, что кто-то пытается поддерживать

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

, изменив его на

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

Если компилятор теперь может доказать, что A всегда является B и связывает Z.f с методом в B, сопровождающий будет сбит с толку.

1 голос
/ 14 марта 2012

Java - это одна отправка, тогда как вы пытаетесь сделать это: двойная отправка (где вызываемый метод зависит как от динамического класса времени выполнения, так и от параметров).

Подписьметод для вызова в Java определяется во время компиляции;это означает, что объявленный класс объекта определяет, с каким методом он связан.Переопределение метода в подклассе влияет на связанную реализацию, но перегрузка метода - нет (поскольку перегруженный метод имеет другую сигнатуру).

В классе B вы перегружаете f () версией, которая принимает intпри использовании объекта, объявленного как принадлежащего классу A, этот метод, по-видимому, не существует (его нельзя вызвать, и он не будет вызываться).

Подводя итог:

  • Компилятор связывается с сигнатурой метода во время компиляции.
  • Эта связанная подпись зависит от объявленного (времени компиляции) типа объекта и параметров.
  • Если метод переопределен в подклассе, затем при вызове подкласса (независимо от объявленного типа) будет выбран переопределенный метод.
  • Перегрузка не переопределяет, для переопределения вам нужна та же сигнатура метода (ну, кроме ковариации).
0 голосов
/ 14 марта 2012

Ну, я могу ошибаться, но если вы связываете объект z типа A с объектом типа B, он все равно будет связываться как тип B, поэтому он выполняет метод в классе B и не в классе A. Обратите внимание, что вы НЕ создаете объект типа A, поскольку вы не используете new.

И, как сказал Майк Самуэль, по умолчанию -6 следует считать int, но это не соответствует вашему объяснению. Я постараюсь найти правильный ответ для этого.

...