domingo, 14 de agosto de 2011

Java - Sobrecarga e Polimorfismo

Relembrando o conceito de assinatura de um método:  nome, número de parâmetros, ordem dos parâmteros e tipos dos parâmetros.  Em alguns contextos dentro do estudo de linguagens de programação, a assinatura também inclui o tipo do valor retornado, mas não no tutorial Java que estamos utilizando.

Em Java, não é possível definir métodos com mesma assinatura na mesma classe.  Porém, é possível definir métodos com mesma assinatura em classes derivadas.  Isto é um caso de Polimorfismo, ou seja, métodos com a mesma assinatura executando ações diferentes.

Métodos de instância podem ser redefinidos (overridden) por uma subclasse; métodos de classe podem ser escondidos (hidden) por uma subclasse.  A tabela abaixo serve de guia para entendermos melhor estes conceitos:

Definindo métodos com a mesma assinatura numa subclasse
Método de instância na superclasse Método de classe na superclasse
Método de instância na subclasse Redefinido Erro de compilação
Método estático na subclasse Erro de compilação Escondido

Com relação ao tipo de retorno, uma subclasse pode restringir o tipo de retorno (ou seja, usar um subtipo dele), mas não pode usar um tipo mais geral ou de outra parte da hierarquia de tipos.

Por outro lado, com relação ao encapsulamento, uma subclasse pode ser menos restritiva na permissão de acesso, mas não mais restritiva.

Note que é um erro de compilação usar a mesma assinatura para métodos de classe na superclasse e métodos de instância na subclasse, ou vice-versa.

A diferença entre redefinir e esconder é a seguinte: o método redefinido, quando chamado, determina o tipo da variável na hora da execução para escolher qual código executar, se o da classe filha ou o da classe mãe.  A isto se chama acoplamento dinâmico. Exemplo:


Arquivo: Animal.java

public class Animal {
    public static void testClassMethod() {
        System.out.println("The class method in Animal.");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Animal.");
    }
}



Arquivo: Cat.java

public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The class method" + " in Cat.");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method" + " in Cat.");
    }
   
    public static void main(String[] args) {
        // Método de classe chamado via classe
        Animal.testClassMethod();
        Cat.testClassMethod();
       
        // Cada macaco no seu galho
        Animal myAnimal = new Animal();
        Cat myCat = new Cat();

        // Método de classe chamado via instância (desencorajado)
        myAnimal.testClassMethod();
        myCat.testClassMethod();
       
        // Método de instância: escolhe em tempo de execução
        myAnimal.testInstanceMethod();
        myCat.testInstanceMethod();

        // Macaco no galho do outro
        myAnimal = myCat;     

        // Método de classe chamado via instância (desencorajado)
        myAnimal.testClassMethod();
        myCat.testClassMethod();

        // Método de instância: escolhe em tempo de execução
        myAnimal.testInstanceMethod();
        myCat.testInstanceMethod();
    }
}


Saída:

The class method in Animal.
The class method in Cat.
The class method in Animal.
The class method in Cat.
The instance method in Animal.
The instance method in Cat.
The class method in Animal.
The class method in Cat.
The instance method in Cat.
The instance method in Cat.


Anotação @Override

Sobrecarga (overloading) é quando métodos de uma mesma classe têm nomes iguais, mas assinaturas diferentes.

Nenhum comentário:

Postar um comentário