Desenvolvimento Web

Programação orientada a objetos: classes, herança e polimorfismo explicados com exemplos reais

Programação orientada a objetos: classes, herança e polimorfismo explicados com exemplos reais

Programação Orientada a Objetos (POO) é um dos paradigmas de programação mais ensinados e mais mal compreendidos. Muitos desenvolvedores aprendem a sintaxe — como declarar uma classe, como criar objetos — sem entender os princípios por trás: por que usar classe em vez de funções simples? Quando herança ajuda e quando atrapalha? O que polimorfismo resolve na prática? Este guia usa exemplos concretos para que esses conceitos façam sentido além da teoria.

Por que existem objetos e classes?

Imagine que você precisa representar 1000 produtos em um sistema de e-commerce. Sem classes, você teria 1000 variáveis separadas para nome, 1000 para preço, 1000 para estoque — e funções avulsas que recebem esses dados. Classes agrupam dados (atributos) e comportamentos (métodos) relacionados em uma unidade coesa. O produto sabe seu preço, sabe calcular seu desconto, sabe verificar se tem estoque — a lógica fica dentro do objeto, junto dos dados que ela manipula.

Classes em Python: o básico

class Produto:
    def __init__(self, nome, preco, estoque):
        self.nome = nome
        self.preco = preco
        self.estoque = estoque

    def calcular_preco_com_desconto(self, percentual):
        return self.preco * (1 - percentual / 100)

    def tem_estoque(self):
        return self.estoque > 0

    def vender(self, quantidade):
        if quantidade > self.estoque:
            raise ValueError(f"Estoque insuficiente. Disponível: {self.estoque}")
        self.estoque -= quantidade
        return f"{quantidade}x {self.nome} vendido(s). Estoque restante: {self.estoque}"

    def __repr__(self):
        return f"Produto('{self.nome}', R${self.preco:.2f}, estoque={self.estoque})"

# Criando objetos (instâncias)
camiseta = Produto("Camiseta Tech", 89.90, 50)
notebook = Produto("Notebook i5", 3200.00, 5)

print(camiseta.calcular_preco_com_desconto(10))   # 80.91
print(notebook.tem_estoque())                      # True
print(camiseta.vender(3))                          # 3x Camiseta Tech vendido(s)...

Herança: especializar sem duplicar código

Herança permite que uma classe “filha” herde atributos e métodos de uma classe “pai”, adicionando ou sobrescrevendo comportamentos específicos:

class ProdutoDigital(Produto):
    def __init__(self, nome, preco, url_download):
        super().__init__(nome, preco, estoque=9999)  # Estoque ilimitado
        self.url_download = url_download

    def vender(self, quantidade):
        # Produto digital não reduz estoque
        return f"Acesso liberado para '{self.nome}'. Download: {self.url_download}"

class ProdutoPerecivel(Produto):
    def __init__(self, nome, preco, estoque, data_validade):
        super().__init__(nome, preco, estoque)
        self.data_validade = data_validade

    def esta_vencido(self):
        from datetime import date
        return date.today() > self.data_validade

ebook = ProdutoDigital("Curso Python", 79.90, "https://curso.com/downloads/python")
leite = ProdutoPerecivel("Leite Integral", 5.50, 100, date(2026, 4, 1))

print(ebook.vender(1))           # Acesso liberado...
print(leite.esta_vencido())      # False

Polimorfismo: tratando objetos diferentes da mesma forma

# O polimorfismo permite tratar instâncias de subclasses uniformemente
produtos = [
    Produto("Camiseta", 89.90, 50),
    ProdutoDigital("Ebook Python", 49.90, "https://..."),
    ProdutoPerecivel("Iogurte", 4.20, 80, date(2026, 3, 20)),
]

# O método vender() se comporta diferente para cada tipo
# mas pode ser chamado da mesma forma para todos
for produto in produtos:
    print(produto.vender(1))

Polimorfismo é o que torna possível escrever código genérico que funciona com tipos diferentes sem precisar de if/elif checker — cada objeto sabe como responder ao mesmo “pedido” de acordo com sua natureza.

Quando NÃO usar herança

Herança é frequentemente mal usada — desenvolvedores criam hierarquias profundas e frágeis onde composição seria mais simples. A regra geral: prefira herança apenas quando existe uma relação “é um” genuína (ProdutoDigital É UM Produto). Para relações “tem um” (Pedido TEM UM Cliente), use composição — o Pedido recebe um objeto Cliente como parâmetro. Hierarquias profundas de herança (A herda B que herda C que herda D) criam código difícil de entender e modificar — se você está mais de dois níveis de profundidade, considere refatorar com composição.

Tem um projeto em mente?

Somos especialistas em transformar ideias em produtos digitais. Apps, sites, automações e IA — vamos construir juntos.

Resposta rápida Orçamento sem compromisso +100 projetos entregues
Compartilhar: