1
resposta

Quando no Polimorfismo usar o Tipo da referencia da Classe Mãe ou da Filha?

Na aula de Polimorfismo de Java, durante a explicação, usou-se o codigo abaixo:

            Funcionario g1 = new Gerente();

Porém depois na explicação prática usou-se: Gerente g1 = new Gerente();

Então não entendi a diferente e a necessidade de se usar o tipo mais Generico na declaração do objeto

1 resposta

Gustavo,

A grande sacada de conseguir fazer

Funcionario teste = new Gerente();

É que conseguimos fazer um código muito mais reaproveitável, pois trabalhamos de maneira mais abstrata. Podemos trabalhar com qualquer classe que herde de Funcionario. Podemos definir um método em Funcionário que todos os filhos sobrescrevem, e na prática, nos referenciaremos pelo método de Funcionário, porém será executado, em tempo de execução, o método da classe herdeira de funcionário.

Imagine que você tenha o código abaixo:

class Funcionario {
    double calcSalario() {
        return valorDia*22;
    }
}

class Gerente extends Funcionario {
    @Override
    double calcSalario() {
        return super.calcSalario()*1.2;
    }
}

A situação é a seguinte: Gerente é um funcionário, porém com um cálculo de salário diferenciado, neste caso, ganha 20% em cima do salário base.

Agora imagina que vc tenha um array de funcionários, que poderão ser da classe Funcionario ou Gerente (ou Diretor, Presidente, etc). Se eu quisesse imprimir o salário de todos os funcionários, poderia ter o seguinte código:

class Relatorio {
    public void imprimirSalarios(Funcionario[] funcionarios) {
        for (Funcionario f: funcionarios) {
            System.out.println(f.calcSalario());
        }
    }
}

Veja que devido ao Polimorfismo, quando o método calcSalario é chamado dentro do for (classe Relatorio), se a instância for de Funcionario a implementação de Funcionario será chamada, mas se a instância for de Gerente então a implementação de Gerente será chamada.

Em C++ o método calcSalario() precisaria ser virtual para termos este comportamento igual ao Java, caso contrário o método chamado iria depender do tipo da referência (Funcionario ou Gerente), por exemplo:

class Funcionario {
    double calcSalario();
}

class Gerente: public Funcionario {
    double calcSalario();
}

Funcionario *f = Gerente();
f->calcSalario(); // Chama a implementacao de Funcionario

Gerente *g = Gerente();
g->calcSalario(); // Chama a implementacao de Gerente

Mas se calcSalario em Gerente fosse definida como virtual, sempre seria chamado a implementação do tipo correto, por exemplo:

class Gerente: public Funcionario {
    virtual double calcSalario();
}

Funcionario *f = Gerente();
f->calcSalario(); // Chama a implementação de Gerente

Espero que tenha ajudado.