Módulo 11 - Orientação a objetos: herança

Polimorfismo na prática

11 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026

O que você vai aprender

  • Guardar objetos de tipos diferentes numa mesma lista.
  • Percorrer essa lista chamando o mesmo método em todos.
  • Evitar cadeias de if por tipo, confiando na sobrescrita.
  • Entender por que adicionar um novo tipo não quebra o laço.

Uma lista de tipos diferentes

Você já viu cada filha sobrescrever falar do seu jeito. O ganho fica evidente quando junta objetos de tipos diferentes numa mesma coleção. Imagine uma lista com um cachorro, um gato e uma vaca. Todos são animais, todos entendem falar, mas cada um responde diferente. Com um laço simples, você pede a todos que falem, e o Python escolhe a versão certa para cada um. O seu código não pergunta quem é quem; ele confia que todo item da lista sabe falar. Essa é a cara do polimorfismo no dia a dia.

class Animal:
    def __init__(self, nome):
        self.nome = nome
    def falar(self):
        return f"{self.nome} faz um som."

class Cachorro(Animal):
    def falar(self):
        return f"{self.nome} faz au au!"

class Gato(Animal):
    def falar(self):
        return f"{self.nome} faz miau!"

class Vaca(Animal):
    def falar(self):
        return f"{self.nome} faz muuu!"

bicharada = [Cachorro("Rex"), Gato("Felix"), Vaca("Mimosa")]
for bicho in bicharada:
    print(bicho.falar())
# Rex faz au au!
# Felix faz miau!
# Mimosa faz muuu!

Um laço, três tipos, três comportamentos: o polimorfismo em ação.

Olhe o laço: ele tem uma linha útil, bicho.falar(). Não há nenhum if perguntando o tipo, nenhuma verificação. Ainda assim, cada bicho fala do seu jeito, porque cada classe sobrescreveu falar. É o Python, na hora da chamada, que resolve qual versão usar, seguindo aquela busca da filha para a base. Compare com o que seria preciso sem polimorfismo, e a diferença de clareza fica gritante.

O que evitamos: a cadeia de if

Sem polimorfismo, a mesma tarefa vira uma cadeia de condições que checa o tipo de cada objeto e decide o som. Funciona, mas envelhece mal. Cada novo animal exige mais um ramo no if, e essa lógica costuma se espalhar por vários pontos do programa, todos precisando ser atualizados juntos. Esquecer um deles cria bugs silenciosos. O trecho abaixo mostra o caminho ruim, só para contraste; ele faz o mesmo que o laço anterior, com muito mais atrito.

def som_ruim(bicho):
    # anti-exemplo: checa o tipo na unha
    if isinstance(bicho, Cachorro):
        return f"{bicho.nome} faz au au!"
    elif isinstance(bicho, Gato):
        return f"{bicho.nome} faz miau!"
    elif isinstance(bicho, Vaca):
        return f"{bicho.nome} faz muuu!"
    return f"{bicho.nome} faz um som."

# Cada animal novo exige mais um elif aqui, e em todo lugar parecido.

O anti-exemplo: cadeia de if por tipo, que cresce a cada animal novo.

Cadeia de if por tipo

  • Um elif novo a cada tipo criado
  • Lógica de som espalhada e repetida
  • Fácil esquecer de atualizar um ponto
  • Quem chama precisa conhecer todos os tipos

Polimorfismo com sobrescrita

  • O novo tipo traz o seu próprio falar
  • O som de cada um mora na sua classe
  • O laço genérico nunca precisa mudar
  • Quem chama só confia no método falar

Extensível quase de graça

A prova real do polimorfismo é adicionar um tipo novo e ver o que muda no código que já existia. Com o laço polimórfico, a resposta é: nada muda. Você cria a classe Pato, sobrescreve falar e a coloca na lista. O laço que percorre a bicharada continua idêntico e já sabe fazer o pato falar, porque ele só chama falar e confia. É o oposto da cadeia de if, onde cada tipo novo obrigaria a caçar e alterar todos os pontos que decidem o som.

class Pato(Animal):
    def falar(self):
        return f"{self.nome} faz quá quá!"

bicharada = [Cachorro("Rex"), Gato("Felix"), Pato("Donald")]
for bicho in bicharada:
    print(bicho.falar())
# Rex faz au au!
# Felix faz miau!
# Donald faz quá quá!  (o laço não mudou nada)

O tipo novo Pato entra na lista e o laço já o trata, sem uma linha alterada.

Teste rápido

Por que o laço que chama bicho.falar() não precisa de if por tipo?

Perguntas frequentes

Preciso que todos os objetos herdem da mesma base para o polimorfismo funcionar?
Ajuda a organizar, mas o Python não exige. Pelo duck typing, basta que cada objeto tenha o método que você vai chamar, como falar. Se todos entendem falar, o laço funciona, tenham eles a mesma base ou não. Uma base comum, porém, deixa a intenção mais clara e evita esquecer um método.
Polimorfismo deixa o código mais lento?
Na prática, não é uma preocupação real neste nível. A escolha da versão do método é feita pelo Python de forma eficiente. O ganho de clareza e de manutenção compensa muito qualquer custo mínimo. Escreva pensando em legibilidade; o polimorfismo é o caminho legível aqui.
E se um objeto da lista não tiver o método chamado?
Aí o Python levanta um AttributeError ao chegar nele. Por isso convém garantir que todos os tipos da coleção compartilhem a mesma interface, ou seja, tenham o método esperado. Uma classe base que define o método, mesmo genérico, ajuda a garantir isso para todas as filhas.
Quando prefiro isinstance a polimorfismo?
isinstance tem seus usos, como validar um argumento na entrada de uma função. Mas escolher comportamento com uma cadeia de isinstance por tipo é o sinal clássico de que polimorfismo resolveria melhor. Se você está decidindo o que fazer com base no tipo, mova esse o quê fazer para dentro de cada classe.
O que é duck typing, citado na aula?
É a ideia de que o tipo não importa, só o comportamento: se o objeto tem o método que você chama, ele serve. O nome vem de se anda e grasna como um pato, é um pato. O Python usa muito esse princípio, e ele convive bem com o polimorfismo por herança.
Posso misturar tipos muito diferentes na mesma lista?
Pode, desde que faça sentido tratá-los pelo mesmo método. Uma lista de figuras que todas têm area() é polimórfica e útil, tema da prática final. Já misturar coisas sem nenhum método em comum não rende polimorfismo; a lista só é útil quando há uma interface compartilhada.

Fontes

Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.