Ligação estática e dinâmica em Java
1. Introdução
Polymorphism permite que um objeto assuma várias formas - quando um método exibe polimorfismo, o compilador deve mapear o nome do método para a implementação final.
Se for mapeado em tempo de compilação, é uma vinculação estática ou inicial.
Se for resolvido no tempo de execução, é conhecido como vinculação dinâmica ou tardia.
2. Compreendendo através de um código
Quando uma subclasse estende uma superclasse, ela pode reimplementar os métodos definidos por ela. Isso é chamado de substituição de método.
Por exemplo, vamos criar uma superclasseAnimal:
public class Animal {
static Logger logger = LoggerFactory.getLogger(Animal.class);
public void makeNoise() {
logger.info("generic animal noise");
}
public void makeNoise(Integer repetitions) {
while(repetitions != 0) {
logger.info("generic animal noise countdown " + repetitions);
repetitions -= 1;
}
}
}
E uma subclasseDog:
public class Dog extends Animal {
static Logger logger = LoggerFactory.getLogger(Dog.class);
@Override
public void makeNoise() {
logger.info("woof woof!");
}
}
Ao sobrecarregar um método, como amakeNoise() da classeAnimal, o compilador resolverá o método e seu código em tempo de compilação. This is an example of static binding.
No entanto, se atribuirmos um objeto do tipoDog a uma referência do tipoAnimal, o compilador resolverá o mapeamento do código de função em tempo de execução. Isso é ligação dinâmica.
Para entender como isso funciona, vamos escrever um pequeno snippet de código para chamar as classes e seus métodos:
Animal animal = new Animal();
// calling methods of animal object
animal.makeNoise();
animal.makeNoise(3);
// assigning a dog object to reference of type Animal
Animal dogAnimal = new Dog();
dogAnimal.makeNoise();
The output of the above code will be:
com.example.binding.Animal - generic animal noise
com.example.binding.Animal - generic animal noise countdown 3
com.example.binding.Animal - generic animal noise countdown 2
com.example.binding.Animal - generic animal noise countdown 1
com.example.binding.Dog - woof woof!
Agora, vamos criar uma classe:
class AnimalActivity {
public static void eat(Animal animal) {
System.out.println("Animal is eating");
}
public static void eat(Dog dog) {
System.out.println("Dog is eating");
}
}
Vamos adicionar a linha à classe principal:
AnimalActivity.eat(dogAnimal);
A saída seria:
com.example.binding.AnimalActivity - Animal is eating
This example shows that a static function undergoes static binding.
O motivo é que as subclasses não podem substituir métodos estáticos. Se a subclasse implementasse o mesmo método, ocultaria o método da superclasse. Similarly, if a method is final or private, the JVM will do a static binding.
Um método de limite estático não está associado a um objeto específico, mas é chamado emType (classe em Java). A execução desse método é marginalmente mais rápida.
Qualquer outro método é automaticamente um método virtual em Java por padrão. A JVM resolve esses métodos no tempo de execução e isso é ligação dinâmica.
A implementação exata depende da JVM, mas seria adotada uma abordagem semelhante ao C ++, onde a JVM consulta a tabela virtual para decidir em qual objeto o método seria chamado.
3. Conclusão
A vinculação é parte integrante de uma linguagem que implementa o polimorfismo, é importante entender as implicações da vinculação estática e dinâmica para ter certeza de que nossos aplicativos estão se comportando como queremos.
Com esse entendimento, no entanto, somos capazes de usar efetivamente a herança de classes e a sobrecarga de métodos.
Como sempre, o código está disponívelover on GitHub.