Dúvida sobre as vantagens de utilizar polimorfismo na chamada de métodos

Pessoal, estou estudando OO em java, e uma das coisas que é possível fazer usando o polimorfismo é poder criar diversos objetos com uma mesma referência; e.g., digamos uma classe Animal, com a referência desta classe Animal eu posso instanciar outros tipos(subtipos) de animais como gato, cachorro, coelho, desde que esses subtipos herdem de Animal. A questão é, qual a vantagem disso? pois essa referência de animal vai poder acessar apenas os métodos das classes dos subtipos.

Você trocou as bolas … Através de uma referência à superclasse, somente os métodos da superclasse são acessíveis.

Imagine que você tem um certo método que aceita um Animal como parametro.

void umMetodoQualquer(Animal animal) { /* ... */ }

Como você mesmo disse, o polimorfismo nos permitiria usar qualquer subtipo de Animal como argumento nesse método.

umMetodoQualquer( new Gato );
umMetodoQualquer( new Cachorro );

Sem isso, teriámos que criar um método para cada tipo possível.

void umMetodoQualquer(Animal animal) { /* ... */ }
void umMetodoQualquer(Cachorro cachorro) { /* ... */ }
void umMetodoQualquer(Gato gato) { /* ... */ }
/* ... */

O que seria um pesadelo. Então esta é a primeira vantagem.

Quanto a apenas poder acessar métodos da super classe, isso não é um problema, mas sim o mérito do polimorfismo.

Se eu decidi criar uma classe Animal da qual todos os animais herdarão, é porque eu identifiquei que todos os animais possuem comportamentos semelhantes, então é natural que eu represente esses comportamentos através de métodos na super classe e que, em cada sub classe, eu sobreescrever esses métodos personalizando-os para a necessidade de cada animal.

Pense que todo animal emite algum tipo de som.

abstract class Animal {
    abstract public void emitirSom();
}

E que cada animal emite sons diferentes.

class Cachorro extends Animal {
    public void emitirSom() {
        System.out.println("AU AU!!!");
    }
}

class Gato extends Animal {
    public void emitirSom() {
        System.out.println("MIAU MIAU!!!");
    }
}

Agora pense que umMetodoQualquer seja implementado da seguinte forma:

void umMetodoQualquer(Animal animal) {
    animal.emitirSom();
}

Polimorfismo permite que ao fazermos isso:

umMetodoQualquer( new Gato );
umMetodoQualquer( new Cachorro );

O resutado seja esse:

MIAU MIAU!!!
AU AU!!!

Se Gato faz coisas que apenas gatos fazem, nem faria sentido usar:

Animal animal = new Gato();

Mas sim:

Gato gato = new Gato();
1 curtida