Guia de estudo

04/05/2026 · Aula 08

Herança Avançada

Especialização e Multiplicidade

Programação Orientada a Objetos com Python
Tecnologia em Análise e Desenvolvimento de Sistemas

MRO (C3 Linearization) Method Override Mixins Architecture super() Delegation

plano de voo

Objetivos de Aprendizagem

01

Recap: Aula 07

Revisão dos fundamentos de herança simples e inicialização de atributos.

02

Sobrescrita

Dominar a redefinição de comportamentos em subclasses.

03

Multiplicidade

Compor objetos a partir de múltiplas bases sem ambiguidade.

04

MRO & C3

O algoritmo de busca de métodos do Python.

recapitulação · parte 1

Fundamentos da Aula 07

  • 🧬 Conceito: A subclasse herda atributos e métodos, especializando o comportamento.
  • 🚗 Exemplo: Carro 'é um' Veículo. Ele aproveita o motor e rodas, mas adiciona portas.

Lembrete

Herança modela taxonomia. Se a relação for 'possui um', usamos Composição.

recapitulação · parte 2

A Regra de Ouro do super()

Vimos que se a filha define __init__, ela esconde o do pai. O super() resolve isso.

recap_super.py
class Veiculo:
    def __init__(self, marca):
        self.marca = marca

class Carro(Veiculo):
    def __init__(self, marca, portas):
        # Chamada obrigatória para manter o DNA
        super().__init__(marca)
        self.portas = portas

fundamentação

O Mecanismo de Sobrescrita

  • 🏗️ Definição: O método na filha deve ter exatamente o mesmo nome do método no pai.
  • 🎯 Propósito: Permitir que o filho se comporte de forma única, respeitando a mesma interface.

Importante

Ao sobrescrever, você decide se quer substituir totalmente o pai ou apenas adicionar novos passos.

delegação avançada

Extensão via super()

  • 🔗 Extensão: Executa o código base e incrementa com lógica nova.
  • 🚫 Substituição: Ignora a base (quando não chamamos o super()).

override na prática

Especializando o Cálculo de Bônus

Neste sistema de RH, o bônus é calculado de forma diferente dependendo do cargo hierárquico.

rh_override.py
class Funcionario:
    def __init__(self, salario):
        self.salario = salario

    def calcular_bonus(self):
        return self.salario * 0.10

class Gerente(Funcionario):
    def calcular_bonus(self):
        # Substitui totalmente o cálculo do pai
        return self.salario * 0.25

super() em métodos

Gratificação Cumulativa

Vamos garantir que o Gerente ganhe o bônus padrão de 10% MAIS uma gratificação fixa.

rh_extensao.py
class Gerente(Funcionario):
    def calcular_bonus(self):
        # Delega o cálculo de 10% para o pai
        base = super().calcular_bonus()
        return base + 500.00

arquitetura de sistemas

Herança Múltipla

  • 🧬 Conceito: Capacidade de unir funcionalidades de dois ou mais 'pais' em um único objeto.
  • ⚠️ Risco: Pode gerar ambiguidade e complexidade se a hierarquia não for bem planejada.

Mercado

Frameworks como Django e Odoo utilizam esta técnica exaustivamente para injetar funcionalidades (Mixins).

herança múltipla · sintaxe

Múltiplas Bases em Ação

Antes dos problemas, veja a beleza: uma classe pode herdar de duas bases independentes e ganhar todos os seus comportamentos de uma só vez.

A sintaxe é simples: class Filha(Base1, Base2)
🎯
Pato não implementa nada — herda tudo das duas bases.
📐
Funciona perfeitamente quando as bases são ortogonais: sem métodos em conflito.
⚠️
A ordem de declaração importa: o Python lê da esquerda para a direita ao resolver conflitos.
heranca_multipla_basica.py
class Ave:
    def voar(self):
        print("🐦 Batendo asas...")

class Nadador:
    def nadar(self):
        print("🏊 Nadando...")

# Pato herda de DUAS bases independentes
class Pato(Ave, Nadador):
    pass

donald = Pato()
donald.voar()   # Herdado de Ave
donald.nadar()  # Herdado de Nadador

laboratório prático

Case: Automação Smart Home

  • 💡 Base: Dispositivo (marca, modelo, ligado).
  • 📶 Mixin: ConectavelMixin (capacidade de Wi-Fi).

Desafio

Criar uma SmartLamp que herda a física da Lâmpada e a inteligência do Mixin.

prática · passo 1

Dispositivo e Sobrescrita

A base define identidade (marca e modelo) e estado elétrico. O método ligar() é a operação fundamental que as subclasses poderão estender.

smarthome_base.py
class Dispositivo:
    def __init__(self, marca, modelo):
        self.marca = marca
        self.modelo = modelo
        self.ligado = False

    def ligar(self):
        self.ligado = True
        print(f"[{self.marca} {self.modelo}] Ligado.")

    def status(self):
        return "Ligado" if self.ligado else "Desligado"

prática · passo 2

Extensão com super()

O Ar-Condicionado usa o pai para ligar, mas já define uma temperatura de conforto imediatamente.

smarthome_ext.py
class ArCondicionado(Dispositivo):
    def ligar(self):
        super().ligar() # Ativa a energia no pai
        self.temp = 22
        print(f"Resfriando ambiente para {self.temp}°C")

prática · passo 3

O Plugin: ConectavelMixin

Este Mixin não é um dispositivo independente, é uma capacidade plugável de rede.

smarthome_mixin.py
class ConectavelMixin:
    def conectar_wi_fi(self):
        print(f"[{self.marca}] Conectado à rede local.")

    def enviar_dados(self, dados):
        print(f"Sincronizando: {dados}")

laboratório · composição

Montando a SmartLamp

A herança múltipla permite 'montar' o dispositivo com as peças que precisamos.

1. Comportamento Físico

Herda de Lâmpada (que herda de Dispositivo) para ter brilho e energia.

2. Comportamento Digital

Herda de ConectavelMixin para ganhar métodos de rede e telemetria.

3. Resolvendo Conflitos

Uso do MRO para definir se o status vem da lâmpada ou da conexão.

4. Resultado Final

Um objeto único que responde a comandos de voz e interruptores físicos.

laboratório · passo 4

Implementando a SmartLamp

Unindo o mundo físico ao digital. Note a ordem das classes na herança.

smarthome_final.py
class Lampada(Dispositivo):
    def status(self):
        return f"Luz: {super().status()}"

class SmartLamp(Lampada, ConectavelMixin):
    def status(self):
        base = super().status()
        return f"{base} | Sincronizado: SIM"

obj = SmartLamp("Philips", "Hue")
obj.conectar_wi_fi()

conflitos de nomes

O Problema do Diamante

Quando duas classes irmãs herdam do mesmo pai e sobrescrevem o mesmo método, qual das duas vence em D(B, C)?

diamond_case.py
class A:
    def identificar(self):
        print("Sou A — a raiz")

class B(A):
    def identificar(self):
        print("Sou B — filho esquerdo")

class C(A):
    def identificar(self):
        print("Sou C — filho direito")

class D(B, C):
    pass

obj = D()
obj.identificar()
Execute e observe: qual mensagem aparece? Por quê? A resposta está no MRO — próximo slide.

ciência da computação

O Algoritmo MRO — por que B venceu?

O Python não chuta. Ele percorre uma lista ordenada chamada MRO até encontrar o método. Veja a lista de D e acompanhe o raciocínio.

📋
O MRO é uma lista linear gerada uma vez na criação da classe.
🔎
A busca percorre a lista da esquerda para a direita e para no primeiro match.
📐
B vence porque D(B, C) coloca B antes de C na declaração.
🔁
Troque para D(C, B) e o resultado muda: Sou C — filho direito.
diamond_mro.py
print(D.__mro__)
# (<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>)

# Python percorre da esquerda para a direita:
# 1. D  → não tem identificar()  → continua
# 2. B  → tem identificar()      → EXECUTA e para
# 3. C, A, object nunca chegam a ser visitados

obj = D()
obj.identificar()
# Sou B — filho esquerdo

debug de hierarquia

Inspecionando o MRO da SmartLamp

Sempre verifique a ordem de resolução em casos de herança múltipla para evitar bugs de execução.

mro_debug.py
print(SmartLamp.__mro__)
# Resultado: (SmartLamp, Lampada, Dispositivo, ConectavelMixin, object)

check-list técnico

Regras Críticas do MRO

O interpretador Python nunca erra a ordem. Você também não deveria.

1

Precedência da Instância

A busca começa sempre no nível mais baixo (subclasse) e sobe lateralmente.

2

Ordem de Declaração

No caso (B, C), B tem prioridade por ser o primeiro argumento declarado.

3

A Terminação object

Toda busca em Python termina na classe object, a raiz de todos os tipos.

guia de arquitetura

Estratégias de Composição

Como escolher a estrutura correta para seu sistema?

Prefira Herança Múltipla se

  • Usa Mixins (Plugins de comportamento)
  • As bases são independentes (ortogonais)
  • Precisa de polimorfismo em vários eixos

Prefira Composição se

  • A relação não é 'É UM'
  • Conflitos de nomes no MRO são frequentes
  • A hierarquia está ficando muito profunda

encerramento · teoria

O que dominamos hoje

  • Override — Redefinição técnica de métodos.
  • super() — Delegação eficiente entre níveis hierárquicos.
  • Herança Múltipla — Composição de classes híbridas.
  • MRO — Entendimento do algoritmo C3 Linearization.
  • Mixins — Padrões plugáveis de arquitetura.

consolidação

Desafios de Implementação

Aplicação prática dos conceitos de Override, super() e Herança Múltipla.

01–02

Nível Fácil

Override puro: substituição total de comportamento.

03–04

Nível Médio

Extensão com super() em hierarquias reais.

05

Nível Difícil

Arquitetura com Mixins seguindo o padrão Smart Home.

06

Nível Expert

Rastreio completo do MRO no grafo do diamante com super() em cadeia.

prática · fácil

Fácil: Override Puro

01

Sons de Fazenda

Crie Animal com o método falar() imprimindo 'Som genérico'. Implemente subclasses Cachorro e Gato sobrescrevendo falar() com seus respectivos sons. Instancie cada uma e confirme o override.

02

Internacionalização

Crie Pessoa com saudar() retornando 'Hello!'. Implemente Brasileiro(Pessoa) sobrescrevendo saudar() para retornar 'Olá!'. Instancie ambas e confirme que cada uma responde diferente.

prática · médio

Médio: Regras Estendidas

03

Taxas de Saque

Crie ContaBancaria com sacar(valor) que desconta o valor do saldo. Implemente ContaCorrente(ContaBancaria) sobrescrevendo sacar(): use super() para executar o saque normal e depois deduza uma taxa adicional de R$ 2,00. Mostre o saldo antes e depois.

04

Cadastro Aluno

Crie Pessoa com __init__(nome, idade). Implemente Aluno(Pessoa) adicionando o atributo matricula, garantindo a chamada de super().__init__(nome, idade). Instancie um Aluno e imprima todos os seus atributos.

prática · difícil/expert

Avançado: Mixins e MRO

05

Smart Garden

Crie Dispositivo(marca, modelo) com ligar(). Implemente AgendamentoMixin com agendar(horario) que imprime o horário de ativação. Crie Irrigador(Dispositivo, AgendamentoMixin) e demonstre chamando ligar() e agendar('06:00').

06

Rastreio Diamante

Reimplemente a hierarquia A, B(A), C(A), D(B, C). Em cada identificar(), chame super().identificar() antes de imprimir a própria mensagem. Chame obj.identificar() e observe todos os níveis aparecerem em sequência — o MRO em ação.

próxima aula

Aula 9 · 06/05

Polimorfismo e Duck Typing

A arte de tratar objetos diferentes através de uma interface comum sem herança rígida.

Abstract Classes Interfaces Late Binding Duck Typing