Верно ли это в отношении позднего связывания?

Я читал в разделе «Думая о java» в главе «Полиморфизм» о концепции «позднего связывания», я просто хочу знать, верно ли мое понимание этой концепции.

Например, процедурные языки знают, где находится функция, которую нужно выполнить до выполнения.

if(condition){func1();}else{func2();}

Таким образом, адрес каждой возможной функции известен точно и до запуска программы, поэтому она легко компилируется, но в OOLs исследуйте этот код,,

makeItSpeak(Animal a ){
  a.speak();
}

Хотя a может быть dog , cat или любым другим типом Animal , а поскольку мы инициализируем объекты во время выполнения, мы должны передать аргумент, по которому мы запускаем говорить во время выполнения, так что это позднее связывание, которое происходит при запуске -время ....

ЭТО ПРАВДА ??


person 3m masr    schedule 01.10.2010    source источник


Ответы (4)


Да, и это реализовано с помощью таблицы виртуальных методов.

В вашем примере speak() — это виртуальный (абстрактный) метод, не имеющий физического адреса. Во время выполнения, в зависимости от типа конкретного подкласса Animal, среда выполнения определяет, какую реализацию speak() вызывать, обращаясь к таблице виртуальных методов.

person oksayt    schedule 01.10.2010

Да. Например,

class A {
  void a() { System.out.println("A"); }
}

class B extends A {
  void a() { System.out.println("B"); }
}

class C {
  public static void main (String[] args) {
    A anA = new B();
    anA.a();  // This will print B
  }
}

Несмотря на то, что переменная anA имеет тип A, экземпляр B может быть определен только во время выполнения.

Суть этого правила в статических методах, которые связываются во время компиляции, так что будьте осторожны.

person leonm    schedule 01.10.2010

Да вы правы. В приведенном вами примере правильный вызов speak() зависит от типа объекта, который будет известен во время выполнения. Только когда вы объявляете метод как final, он подлежит раннему связыванию.

person Sagar V    schedule 01.10.2010
comment
Да, потому что в этом случае мы заранее знаем адрес метода, причина в том, что мы знаем, что нужный метод является методом суперкласса, это правда? - person 3m masr; 01.10.2010
comment
@3m masr: когда вы объявляете метод окончательным, вы гарантируете, что этот метод не будет переопределен в дальнейшем. Следовательно, нет вопроса о том, какой дескриптор объекта будет использоваться, и поэтому компилятор будет оптимизировать. - person Sagar V; 01.10.2010
comment
Это относится только к типу, который объявляет ключевое слово final и его потомков. Если B расширяет A, A определяет метод foo(), а B переопределяет его окончательной реализацией, то при столкновении с A a.foo() во время выполнения поздняя привязка все равно будет необходима. - person oksayt; 01.10.2010

Да, вы правильно поняли. Это делает код более расширяемым и мощным.

person fastcodejava    schedule 01.10.2010