Polimorfismo
O polimorfismo é um dos pilares da Programação Orientada a Objetos (POO) que permite que métodos com o mesmo nome se comportem de maneira diferente em classes distintas. Em Python, ele é implementado principalmente por meio de:
- Sobrescrita de métodos (herança)
- Duck Typing (tipagem dinâmica)
- Sobrecarga de operadores
Polimorfismo por sobrescrita de métodos
Quando uma subclasse redefine um método da superclasse, adaptando-o ao seu contexto.
class Animal:
def emitir_som(self):
return "Som genérico"
class Cao(Animal):
def emitir_som(self): # Sobrescreve o método da superclasse
return "Au au!"
class Gato(Animal):
def emitir_som(self): # Sobrescreve o método da superclasse
return "Miau!"
# Uso
gato = Gato()
gato.emitir_som()
cao = Cao()
cao.emitir_som()
Output:
Au au!
Miau!
Tanto Cao
quanto Gato
herdam emitir_som()
de Animal
, mas cada um implementa seu próprio comportamento.
Polimorfismo por tipagem dinâmica
O Python não verifica tipos rigidamente. Se um objeto tem o método necessário, ele pode ser usado, mesmo sem herança.
class Circulo:
def area(self, raio):
return 3.14 * raio ** 2
class Quadrado:
def area(self, lado):
return lado ** 2
def calcular_area(forma, medida):
return forma.area(medida)
# Uso
print(calcular_area(Circulo(), 5)) # Saída: 78.5
print(calcular_area(Quadrado(), 4)) # Saída: 16
A função calcular_area()
aceita qualquer objeto com o método area()
, independentemente da classe.
Polimorfismo por sobrecarga de operadores
O polimorfismo em Python por sobrecarga de operadores permite que operadores padrão, como +
, -
, *
, etc., tenham comportamentos personalizados quando aplicados a objetos de classes definidas pelo usuário. Isso é feito implementando métodos especiais conhecidos como “métodos mágicos” ou “dunder methods” (como __add__
, __eq__
, etc.) nas suas classes.
Como funciona a sobrecarga de operadores em Python:
- Você define métodos especiais dentro da sua classe para “ensinar” o Python como deve se comportar ao usar um operador com objetos dessa classe.
- Por exemplo, ao implementar o método
__add__
, permite que o operador+
funcione entre dois objetos da sua classe. O mesmo vale para outros operadores (__sub__
para-
,__mul__
para*
, etc.). - Exemplo:
class Fracao:
def __init__(self, numerador, denominador):
self.numerador = numerador
self.denominador = denominador
def __add__(self, outro):
novo_num = self.numerador * outro.denominador + outro.numerador * self.denominador
novo_den = self.denominador * outro.denominador
return Fracao(novo_num, novo_den)
Neste exemplo, pode somar objetos Fracao
usando o operador +
, e o método __add__
será chamado para realizar a lógica específica que você definiu.
Polimorfismo por sobrecarga de operadores:
- O mesmo operador (
+
) pode assumir comportamentos distintos, dependendo do tipo dos objetos envolvidos: pode somar inteiros, concatenar strings ou, se você sobrecarregar, realizar operações específicas em objetos de sua classe. - Esse é um exemplo prático de polimorfismo, pois o operador tem múltiplas “formas” (comportamentos), dependendo do contexto.
Caveat especial em Python:
- Diferente de outras linguagens, Python não suporta sobrecarga de métodos pelo número ou tipo de argumentos (assinatura), mas permite a sobrecarga de operadores via métodos especiais.
- A verificação de tipo é flexível: Python espera que o método esteja disponível no objeto (“duck typing”), não é necessário herdar de uma classe específica.
Exemplo rápido de uso:
na = Fracao(1, 2)
b = Fracao(1, 3)
c = a + b # Usa Fracao.__add__
Neste caso, a + b
funciona porque Fracao
define __add__
.
Resumo dos métodos especiais (mais comuns de operadores):
__add__(self, other)
→ +__sub__(self, other)
→ –__mul__(self, other)
→ *__eq__(self, other)
→ ==__lt__(self, other)
→ <- …e muitos outros.