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.
Ouvir o resumo desta aula
Um recap de cerca de 2 minutos na voz do Valim, para ouvir no trânsito ou na academia.
Ler a transcrição do resumo
Resumo da aula: Polimorfismo na prática.
Os objetivos desta aula. 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.
Veja o essencial, parte por parte.
Uma lista de tipos diferentes. Polimorfismo é o mesmo comando gerando comportamentos diferentes por tipo.
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.
Extensível quase de graça. Você tem vários tipos que fazem a mesma coisa de jeitos diferentes.
Esse foi o resumo do essencial. Para se aprofundar, leia a aula completa e responda os exercícios.
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.