W Javie mechanizm dynamicznego wiązania (dynamic binding) określa, która metoda zostanie wywołana w czasie wykonywania (runtime), a nie podczas kompilacji. Główna różnica w porównaniu do stycznego wiązania (static binding) polega na tym, że statycznie wiązane są na przykład metody private, static, final oraz metody, które nie są nadpisywane w runtime (wiązanie odbywa się na etapie kompilacji), natomiast dynamicznie — zwykłe metody instancji (w tym nadpisane). To umożliwia polimorfizm.
Przykład:
class Animal { void makeSound() { System.out.println("Some sound"); } } class Dog extends Animal { void makeSound() { System.out.println("Bark"); } } public class Test { public static void main(String[] args) { Animal a = new Dog(); a.makeSound(); // Wyświetli: Bark (dynamiczne wiązanie) } }
Tutaj metoda makeSound() jest wiązana dynamicznie — JVM określa, którą wersję wywołać, dopiero w czasie wykonywania.
Pytanie: "Jeśli zadeklarujesz zmienną typu interfejsu lub klasy abstrakcyjnej i przypiszesz jej instancję klasy potomnej, która metoda zostanie wywołana przy dostępie do nadpisanej metody? Jak kompilator to określa?"
Często popełniane błędy: wielu uważa, że wywołanie metody odbywa się na podstawie typu referencji na etapie kompilacji, ale dokonuje tego JVM na etapie wykonywania.
Poprawna odpowiedź: JVM używa typu rzeczywistego obiektu do wywołania metody (dynamiczne wiązanie), a nie typu referencji.
Shape s = new Circle(); s.draw(); // zostanie wywołana draw() z Circle, a nie z Shape
Historia
W dużym projekcie bankowym jeden programista nadpisał metody toString() i equals(), sądząc, że jeśli zadeklaruje zmienną przez interfejs, to wywoła się metoda z interfejsu. Spowodowało to błędne porównanie obiektów — porównywano referencje, a nie wartości, co doprowadziło do błędnej logiki porównania klientów przy wyszukiwaniu duplikatów.
Historia
W projekcie e-commerce, programista stworzył klasę bazową Product i dziedziczącą ElectronicProduct. W tablicy Product[] zapisano obiekty obu typów. Podczas wywołania produktu przez metodę, nadpisaną w ElectronicProduct, wyświetlana była tylko informacja z klasy bazowej, ponieważ wywołana została metoda statyczna! Błąd zauważono przed publikacją.
Historia
W projekcie modelowania transportu użyto wzorca Factory. Programista nie zauważył, że pracuje z polami, a nie z metodami: dostęp do pola klasy pochodnej prowadził do zwrócenia wartości klasy bazowej, a nie nadpisanej, ponieważ pola nie są polimorficzne! System nieprawidłowo obliczał trasy, wyświetlając wszystkim obiektom typ "Transport".