Ligação estática e dinâmica em Java

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.