Guia de estudo

22/04/2026 · Aula 06

Revisão geral

& Mini projeto

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

4 horas Revisão + Prática Sistema de RPG Mini projeto em dupla

agenda

O que vamos fazer hoje

01

Revisão ativa

Construímos um sistema de RPG do zero, aplicando tudo que vimos nas aulas 01 a 05 — passo a passo, conceito por conceito.

02

Mini projeto em dupla

Cada dupla recebe um tema e tem a aula pra implementar um sistema usando todos os conceitos. Vale ponto.

A revisão não é passiva — vamos escrever código junto. Abra o VS Code.

revisão · apresentação

O sistema que vamos construir

Vamos criar um sistema de RPG simples, construído do zero — evoluindo a cada conceito revisado, das aulas 01 a 05.

⚔️

Personagem

Atributos de classe e instância, validação no __init__, parâmetros opcionais, encapsulamento com @property

🎒

Inventário

Composição — nasce dentro do Personagem. Métodos de lista: append, remove, join

🏰

Guilda

Agregação — existe de forma independente. @classmethod e factory methods no Personagem

Ao final teremos um sistema completo com todos os conceitos das aulas 01 a 05.

revisão · aula 02 + aula 03 · atributos de classe e de instância

Atributos de classe vs atributos de instância

Atributos de classe são compartilhados por todos os objetos. Atributos de instância pertencem a cada objeto individualmente.

🏛️
Atributo de classe: definido fora do __init__, compartilhado por todos os objetos
👤
Atributo de instância: definido com self. no __init__, único por objeto
Validação no __init__ garante que o objeto nasce sempre em estado válido
personagem.py
class Personagem:

    # ── Atributos de CLASSE ──────────────────────
    CLASSES_VALIDAS    = ["Guerreiro", "Maga", "Arqueira", "Paladino"]
    _total_personagens = 0

    def __init__(self, nome, classe, nivel=1, vida=100, mana=50):
        # Validação no __init__
        if not nome or not nome.strip():
            raise ValueError("Nome não pode ser vazio.")
        if classe not in Personagem.CLASSES_VALIDAS:
            raise ValueError(f"Classe inválida. Escolha: {Personagem.CLASSES_VALIDAS}")
        if nivel < 1:
            raise ValueError("Nível mínimo é 1.")

        # ── Atributos de INSTÂNCIA ───────────────
        self._nome    = nome.strip()
        self._classe  = classe
        self._nivel   = nivel
        self._vida    = vida
        self._mana    = mana
        self.VIDA_MAX = vida
        self.MANA_MAX = mana
        self.inventario = Inventario()           # composição
        self.guilda     = None                   # agregação (opcional)

        Personagem._total_personagens += 1

# Atributo de classe: mesmo valor em todos
heroi = Personagem("Aria", "Maga")
vilao = Personagem("Krath", "Guerreiro", nivel=5, vida=200)

print(Personagem._total_personagens)  # 2 — compartilhado
print(heroi._total_personagens)       # 2 — mesmo valor

# Atributo de instância: cada um tem o seu
print(heroi.VIDA_MAX)   # 100
print(vilao.VIDA_MAX)   # 200 — diferente!

revisão · aula 03 · métodos de classe

Métodos de classe — @classmethod

Um método de classe recebe cls em vez de self. Age sobre a classe — não sobre uma instância específica.

🏛️
@classmethod recebe cls — referência à classe, não ao objeto
🏭
Factory method: cria objetos com configurações pré-definidas sem passar todos os parâmetros
⚖️
Método de instância age sobre self. Método de classe age sobre cls
personagem.py
class Personagem:

    CLASSES_VALIDAS    = ["Guerreiro", "Maga", "Arqueira", "Paladino"]
    _total_personagens = 0

    # ... __init__ ...

    # ── Métodos de CLASSE ────────────────────────
    @classmethod
    def total_criados(cls):
        return cls._total_personagens

    @classmethod
    def criar_guerreiro(cls, nome):
        return cls(nome, "Guerreiro", nivel=1, vida=150, mana=30)

    @classmethod
    def criar_maga(cls, nome):
        return cls(nome, "Maga", nivel=1, vida=80, mana=120)


# Método de classe — chamado na classe, não no objeto
heroi     = Personagem.criar_maga("Aria")       # factory method
tank      = Personagem.criar_guerreiro("Brom")

print(Personagem.total_criados())  # 2

# Método de instância — chamado no objeto
heroi.atacar(tank)                 # self = heroi

revisão · aula 02 · métodos de instância

O que o personagem sabe fazer

Métodos de instância definem o comportamento do objeto. Sempre recebem self como primeiro parâmetro.

⚔️
atacar(self, alvo) recebe outro objeto — objetos interagem entre si
↩️
esta_vivo() retorna booleano — método com retorno
🔗
curar e subir_nivel usam o setter de vida — encapsulamento já funciona aqui
personagem.py
    # ── Métodos de INSTÂNCIA ─────────────────────
    def atacar(self, alvo):
        dano = 10 * self._nivel
        alvo.vida -= dano
        print(f"{self._nome} causou {dano} de dano em {alvo._nome}!")

    def curar(self, quantidade):
        self.vida += quantidade
        print(f"{self._nome} recuperou {quantidade} de vida!")

    def esta_vivo(self):
        return self._vida > 0

    def subir_nivel(self):
        self._nivel  += 1
        self.VIDA_MAX += 20
        self.vida = self.VIDA_MAX
        print(f"{self._nome} subiu para o nível {self._nivel}!")


heroi = Personagem.criar_maga("Aria")
vilao = Personagem("Krath", "Guerreiro", nivel=5, vida=200)

heroi.subir_nivel()              # nivel=2, vida restaurada ao novo máximo
heroi.atacar(vilao)              # causa dano proporcional ao nível
heroi.curar(30)                  # recupera vida via setter
print(heroi.esta_vivo())         # True

revisão · aula 03 · __str__

Representação legível — __str__

__str__ define o que aparece quando você faz print(objeto). Deve ser clara e útil para o usuário final.

👤
__str__ é para o usuário final — legível e formatado
🎒
Note que {self.inventario} chama o __str__ do Inventário — objetos compostos se exibem em cadeia
⚠️
Sem __str__, print(heroi) mostraria <__main__.Personagem object at 0x...>
personagem.py
    def __str__(self):
        status = "⚔️ vivo" if self.esta_vivo() else "💀 derrotado"
        barra_vida = "█" * (self._vida // 10) + "░" * ((self.VIDA_MAX - self._vida) // 10)
        return (
            f"╔═════════════════════════════════════════╗\n"
            f"║\n"
            f"║  {self._nome:<10} ({self._classe:<10})  \n"
            f"║  Nível: {self._nivel:<3} | {status:<12}  \n"
            f"║  Vida [{barra_vida}] {self._vida}/{self.VIDA_MAX}\n"
            f"║  Mana: {self._mana}/{self.MANA_MAX}\n"
            f"║\n"
            f"╚═════════════════════════════════════════╝"
        )


heroi = Personagem.criar_maga("Aria")
heroi.inventario.adicionar("Cajado Arcano")

print(heroi)
# ╔══════════════════════════╗
# ║  Aria       (Maga      )║
# ║  Nível: 1   | ⚔️ vivo      ║
# ║  Vida [████████░░] 80/80
# ║  Mana: 120/120
# ╚══════════════════════════╝
O __str__ do Personagem chama o __str__ do Inventário automaticamente via f"{self.inventario}" — composição e __str__ trabalhando juntos.

revisão · aula 03 · __repr__

Representação técnica — __repr__

__repr__ é para o desenvolvedor. Aparece no console interativo e deve mostrar como recriar o objeto.

👤
__str__ → para o usuário final: legível e formatado
🛠️
__repr__ → para o desenvolvedor: técnico e reproduzível
💡
Se só implementar um, implemente __repr__ — Python usa ele como fallback para __str__
personagem.py
    def __repr__(self):
        return (f"Personagem(nome='{self._nome}', classe='{self._classe}', "
                f"nivel={self._nivel}, vida={self._vida}, mana={self._mana})")


heroi = Personagem.criar_maga("Aria")

print(str(heroi))    # chama __str__  → ficha formatada
print(repr(heroi))   # chama __repr__ → Personagem(nome='Aria', classe='Maga', nivel=1, vida=80, mana=120)

# No console interativo, digitar o objeto chama __repr__ automaticamente:
# >>> heroi
# Personagem(nome='Aria', classe='Maga', nivel=1, vida=80, mana=120)

revisão · aula 04 · @property e @setter

Controlando acesso — encapsulamento

Os atributos _vida, _mana e _nome são privados. @property e @setter controlam como são lidos e escritos.

👁️
@property — getter: controla como o valor é lido
✏️
@vida.setter — valida e limita antes de salvar
🔐
nome só tem getter — atributo read-only, não pode ser alterado de fora
personagem.py
    # ── @property e @setter ──────────────────────
    @property
    def nome(self): return self._nome            # read-only

    @property
    def vida(self): return self._vida

    @vida.setter
    def vida(self, valor):
        self._vida = max(0, min(int(valor), self.VIDA_MAX))

    @property
    def mana(self): return self._mana

    @mana.setter
    def mana(self, valor):
        self._mana = max(0, min(int(valor), self.MANA_MAX))


heroi = Personagem.criar_maga("Aria")

heroi.vida = -999    # setter: max(0, ...) → _vida = 0
heroi.vida = 9999    # setter: min(..., VIDA_MAX) → _vida = 80
print(heroi.vida)    # getter retorna _vida protegido

# heroi.nome = "X"  → AttributeError: sem setter, é read-only

revisão · aula 05 · composição + métodos de lista

Personagem tem um Inventário

Composição: o Inventário nasce dentro do Personagem e não existe sem ele. Revisamos métodos de lista: append, remove, in, len, join.

📦
Inventario() criado dentro do __init__ do Personagem — nasce e morre com ele
📋
append, remove, in, len, join — métodos de lista em uso real
🔗
print(heroi.inventario) chama o __str__ do Inventário — cada classe cuida da própria exibição
personagem.py
class Inventario:
    """Composição: pertence ao Personagem, não existe sem ele."""

    def __init__(self, capacidade=10):          # parâmetro opcional
        self._itens      = []                   # atributo de instância privado
        self._capacidade = capacidade

    def adicionar(self, item):
        if len(self._itens) >= self._capacidade:
            print("Inventário cheio!")
            return
        self._itens.append(item)

    def remover(self, item):
        if item in self._itens:
            self._itens.remove(item)
        else:
            print(f"'{item}' não encontrado.")

    def __str__(self):
        if not self._itens:
            return "Inventário vazio."
        return f"Itens ({len(self._itens)}/{self._capacidade}): " + " | ".join(self._itens)


# Inventario criado dentro do __init__ do Personagem:
# self.inventario = Inventario()   ← composição

heroi = Personagem.criar_maga("Aria")
heroi.inventario.adicionar("Cajado Arcano")
heroi.inventario.adicionar("Poção de Vida")
heroi.inventario.remover("Poção de Vida")
print(heroi.inventario)
# Itens (1/10): Cajado Arcano

revisão · aula 05 · agregação

Personagem pertence a uma Guilda

Agregação: a Guilda existe independente do Personagem. Ambos criados separadamente e depois relacionados.

🏰
Guilda criada fora do Personagem — ciclo de vida independente
🔗
Personagem recebe a guilda como referência — não a cria
Deletar o personagem não apaga a guilda — diferença central da composição
personagem.py
class Guilda:
    """Agregação: existe independente do Personagem."""

    def __init__(self, nome, nivel_minimo=1):   # parâmetro opcional
        self._nome         = nome
        self._nivel_minimo = nivel_minimo
        self._membros      = []

    def recrutar(self, personagem):
        if personagem._nivel < self._nivel_minimo:
            print(f"Nível insuficiente para entrar em {self._nome}.")
            return
        self._membros.append(personagem)
        print(f"{personagem._nome} entrou na guilda {self._nome}!")

    def listar_membros(self):
        nomes = [p._nome for p in self._membros]
        return ", ".join(nomes) if nomes else "Sem membros."

    def __str__(self):
        return f"Guilda '{self._nome}' — {len(self._membros)} membro(s): {self.listar_membros()}"


# Criados de forma independente — agregação
guilda = Guilda("Os Eternos", nivel_minimo=2)
heroi  = Personagem.criar_maga("Aria")
heroi.subir_nivel()              # nivel=2, agora pode entrar

guilda.recrutar(heroi)           # heroi entra na guilda
heroi.guilda = guilda            # referência ao objeto externo

print(guilda)
# Guilda 'Os Eternos' — 1 membro(s): Aria

del heroi
print(guilda)                    # guilda continua existindo
# Guilda 'Os Eternos' — 1 membro(s): Aria

revisão · aula 05

Composição vs Agregação

A diferença está em quem controla o ciclo de vida do objeto filho.

Composição

  • 📦 Filho criado dentro do pai
  • 📦 Filho não existe sem o pai
  • 📦 Ciclo de vida compartilhado
  • 📦 Personagem → Inventário
  • 📦 Casa → Cômodo
  • 📦 Pedido → Itens do pedido

Agregação

  • 🔗 Filho criado fora e passado ao pai
  • 🔗 Filho existe de forma independente
  • 🔗 Ciclo de vida separado
  • 🔗 Personagem → Guilda
  • 🔗 Aluno → Turma
  • 🔗 Músicas → Playlist

revisão · sistema completo

Tudo junto — o sistema completo

O sistema completo — todas as classes, todos os conceitos das aulas 01 a 05 em um único arquivo.

rpg.py
# ════════════════════════════════════════════════
# Sistema de RPG — código completo
# Conceitos: aulas 01 a 05
# ════════════════════════════════════════════════

class Inventario:
    """Composição: pertence ao Personagem, não existe sem ele."""

    def __init__(self, capacidade=10):          # parâmetro opcional
        self._itens      = []                   # atributo de instância privado
        self._capacidade = capacidade

    def adicionar(self, item):
        if len(self._itens) >= self._capacidade:
            print("Inventário cheio!")
            return
        self._itens.append(item)

    def remover(self, item):
        if item in self._itens:
            self._itens.remove(item)
        else:
            print(f"'{item}' não encontrado.")

    def __str__(self):
        if not self._itens:
            return "Inventário vazio."
        return f"Itens ({len(self._itens)}/{self._capacidade}): " + " | ".join(self._itens)


class Guilda:
    """Agregação: existe independente do Personagem."""

    def __init__(self, nome, nivel_minimo=1):   # parâmetro opcional
        self._nome         = nome
        self._nivel_minimo = nivel_minimo
        self._membros      = []

    def recrutar(self, personagem):
        if personagem._nivel < self._nivel_minimo:
            print(f"Nível insuficiente para entrar em {self._nome}.")
            return
        self._membros.append(personagem)
        print(f"{personagem._nome} entrou na guilda {self._nome}!")

    def listar_membros(self):
        nomes = [p._nome for p in self._membros]
        return ", ".join(nomes) if nomes else "Sem membros."

    def __str__(self):
        return f"Guilda '{self._nome}' — {len(self._membros)} membro(s): {self.listar_membros()}"


class Personagem:

    # ── Atributos de CLASSE ──────────────────────
    CLASSES_VALIDAS    = ["Guerreiro", "Maga", "Arqueira", "Paladino"]
    _total_personagens = 0

    def __init__(self, nome, classe, nivel=1, vida=100, mana=50):
        # Validação no __init__
        if not nome or not nome.strip():
            raise ValueError("Nome não pode ser vazio.")
        if classe not in Personagem.CLASSES_VALIDAS:
            raise ValueError(f"Classe inválida. Escolha: {Personagem.CLASSES_VALIDAS}")
        if nivel < 1:
            raise ValueError("Nível mínimo é 1.")

        # ── Atributos de INSTÂNCIA ───────────────
        self._nome    = nome.strip()
        self._classe  = classe
        self._nivel   = nivel
        self._vida    = vida
        self._mana    = mana
        self.VIDA_MAX = vida
        self.MANA_MAX = mana
        self.inventario = Inventario()           # composição
        self.guilda     = None                   # agregação (opcional)

        Personagem._total_personagens += 1

    # ── @property e @setter ──────────────────────
    @property
    def nome(self): return self._nome            # read-only

    @property
    def vida(self): return self._vida

    @vida.setter
    def vida(self, valor):
        self._vida = max(0, min(int(valor), self.VIDA_MAX))

    @property
    def mana(self): return self._mana

    @mana.setter
    def mana(self, valor):
        self._mana = max(0, min(int(valor), self.MANA_MAX))

    # ── Métodos de INSTÂNCIA ─────────────────────
    def atacar(self, alvo):
        dano = 10 * self._nivel
        alvo.vida -= dano
        print(f"{self._nome} causou {dano} de dano em {alvo._nome}!")

    def curar(self, quantidade):
        self.vida += quantidade
        print(f"{self._nome} recuperou {quantidade} de vida!")

    def esta_vivo(self):
        return self._vida > 0

    def subir_nivel(self):
        self._nivel  += 1
        self.VIDA_MAX += 20
        self.vida = self.VIDA_MAX
        print(f"{self._nome} subiu para o nível {self._nivel}!")

    # ── Métodos de CLASSE ────────────────────────
    @classmethod
    def total_criados(cls):
        return cls._total_personagens

    @classmethod
    def criar_guerreiro(cls, nome):
        return cls(nome, "Guerreiro", nivel=1, vida=150, mana=30)

    @classmethod
    def criar_maga(cls, nome):
        return cls(nome, "Maga", nivel=1, vida=80, mana=120)

    # ── __str__ e __repr__ ───────────────────────
    def __str__(self):
        status = "⚔️ vivo" if self.esta_vivo() else "💀 derrotado"
        barra_vida = "█" * (self._vida // 10) + "░" * ((self.VIDA_MAX - self._vida) // 10)
        return (
            f"╔═════════════════════════════════════════╗\n"
            f"║\n"
            f"║  {self._nome:<10} ({self._classe:<10})  \n"
            f"║  Nível: {self._nivel:<3} | {status:<12}  \n"
            f"║  Vida [{barra_vida}] {self._vida}/{self.VIDA_MAX}\n"
            f"║  Mana: {self._mana}/{self.MANA_MAX}\n"
            f"║\n"
            f"╚═════════════════════════════════════════╝"
        )

    def __repr__(self):
        return (f"Personagem(nome='{self._nome}', classe='{self._classe}', "
                f"nivel={self._nivel}, vida={self._vida}, mana={self._mana})")


# ════════════════════════════════════════════════
# Usando o sistema
# ════════════════════════════════════════════════

heroi  = Personagem.criar_maga("Aria")           # factory method
vilao  = Personagem("Krath", "Guerreiro", nivel=5, vida=200)
guilda = Guilda("Os Eternos", nivel_minimo=2)

heroi.subir_nivel()                              # nivel=2, vida restaurada
guilda.recrutar(heroi)                           # agregação
heroi.guilda = guilda

heroi.inventario.adicionar("Cajado Arcano")      # composição
heroi.inventario.adicionar("Poção de Vida")

while vilao.esta_vivo():
    heroi.atacar(vilao)

print(heroi)                                     # __str__
print(repr(vilao))                               # __repr__
print(guilda)                                    # __str__ da Guilda
print(f"Total de personagens criados: {Personagem.total_criados()}")
Atributos de classe ✅   Atributos de instância ✅   Validação no __init__ ✅   Parâmetros opcionais ✅   Métodos de instância ✅   @classmethod ✅   __str__ ✅   __repr__ ✅   Encapsulamento ✅   Composição ✅   Agregação ✅

revisão · fechamento

O que revisamos hoje

  • Atributos de classe — compartilhados por todos os objetos (CLASSES_VALIDAS, _total_personagens)
  • Atributos de instância — únicos por objeto, definidos com self. no __init__
  • Validação no __init__ — objeto nasce sempre em estado válido, erros levantados na criação
  • Parâmetros opcionais — valores padrão no construtor (nivel=1, vida=100)
  • self — referência ao próprio objeto, primeiro parâmetro de todo método de instância
  • Métodos de instância — agem sobre o objeto: atacar, curar, subir_nivel
  • @classmethod — agem sobre a classe: total_criados(), factory methods
  • __str__ — representação legível para o usuário final
  • __repr__ — representação técnica para o desenvolvedor
  • Encapsulamento — atributos privados com _, @property e @setter com validação
  • Composição — objeto criado dentro do pai, ciclo de vida compartilhado (Personagem → Inventário)
  • Agregação — objeto criado fora e referenciado, ciclo de vida independente (Personagem → Guilda)

mini projeto · apresentação

Agora é com vocês

Cada dupla vai receber um tema e tem a aula pra implementar. O projeto vale ponto e precisa usar tudo que revisamos hoje.

01

Duplas

O professor define as duplas. Ninguém escolhe o parceiro — é treino pra vida real.

02

Sorteio

A ordem é sorteada. O primeiro escolhe o tema, depois o segundo, e assim por diante. Cada tema pode ser escolhido por no máximo duas duplas.

03

Entrega

O código vai para o GitHub. Repositório criado em aula, commit feito antes de sair.

mini projeto · critérios de avaliação

O que será avaliado

⚙️

Código funcionando

O sistema roda sem erros. Inputs e outputs fazem sentido.

🏗️

Uso de classes

__init__, atributos de instância, self e métodos bem definidos.

🔒

Encapsulamento

Atributos privados com _, @property e @setter com validação real.

🔗

Composição ou agregação

Pelo menos um relacionamento entre objetos aplicado corretamente.

📄

__str__ implementado

Cada classe tem um __str__ útil — não vale retornar só o nome.

💡

Originalidade

Ideias próprias além do mínimo: métodos extras, validações criativas, uso de listas.

O mínimo garante a nota. A originalidade faz a diferença.

mini projeto · tema 01

🛵 Delivery de comida

  • 📦 Classe Item — nome, preço, quantidade
  • 🛒 Classe Pedido — lista de itens (composição), taxa de entrega, status
  • 🔒 Encapsulamento — status só pode ser atualizado em sequência válida (recebido → em preparo → saiu → entregue)
  • 📄 __str__ — resumo do pedido com itens, subtotal e total

Desafio extra

Método cancelar() que só funciona se o status for recebido. Depois disso, não dá mais pra cancelar.

mini projeto · tema 02

👟 Loja de tênis

  • 👟 Classe Tenis — marca, modelo, tamanho, preço, estoque
  • 🛒 Classe Carrinho — lista de tênis (composição), métodos adicionar e remover
  • 🔒 Encapsulamento — estoque não pode ficar negativo, preço não pode ser zero ou negativo
  • 📄 __str__ — ficha do produto e resumo do carrinho com total

Desafio extra

Método aplicar_desconto(percentual) no carrinho — valida que o desconto não pode ser maior que 50%.

mini projeto · tema 03

🍕 Pizzaria

  • 🍕 Classe Pizza — sabor, tamanho (P/M/G), preço calculado pelo tamanho
  • 📋 Classe Pedido — lista de pizzas (composição), status, total
  • 🔒 Encapsulamento — tamanho só aceita P, M ou G; status segue fluxo válido
  • 📄 __str__ — comanda do pedido com pizzas, tamanhos e total

Desafio extra

Método adicionar_borda(sabor) na pizza — adiciona R$5,00 ao preço e registra o sabor da borda.

mini projeto · tema 04

🏨 Hotel

  • 🛏️ Classe Quarto — número, tipo, diária, disponibilidade
  • 👤 Classe Hospede — nome, CPF, histórico de estadias (composição interna)
  • 📋 Classe Reserva — hóspede (agregação) + quarto (agregação), datas, total
  • 🔒 Encapsulamento — diária não pode ser negativa, quarto ocupado não pode ser reservado

Desafio extra

Método fazer_checkout() na reserva — libera o quarto e calcula o total com base nos dias de estadia.

mini projeto · tema 05

🏋️ Academia

  • 🏋️ Classe Exercicio — nome, séries, repetições, carga
  • 📋 Classe Treino — lista de exercícios (composição), tipo (A/B/C)
  • 👤 Classe Aluno — nome, peso, altura, IMC calculado, treino atual (composição)
  • 🔒 Encapsulamento — peso e carga não podem ser negativos, IMC calculado automaticamente no setter do peso

Desafio extra

Método classificar_imc() no aluno — retorna Abaixo do peso, Normal, Sobrepeso ou Obesidade com base no IMC.

mini projeto · tema 06

🐾 Clínica veterinária

  • 👤 Classe Dono — nome, telefone, lista de pets (composição)
  • 🐾 Classe Pet — nome, espécie, idade, histórico de consultas (composição)
  • 🩺 Classe Consulta — data, diagnóstico, veterinário, custo
  • 🔒 Encapsulamento — custo não pode ser negativo, idade não pode ser zero ou negativa

Desafio extra

Método ultimo_diagnostico() no pet — retorna o diagnóstico da consulta mais recente ou uma mensagem se não houver histórico.

mini projeto · execução

Como vai funcionar

1

Formação das duplas

O professor define as duplas agora. Se a turma for ímpar, um trio é formado.

2

Sorteio da ordem

A ordem de escolha é sorteada. Cada dupla na sua vez escolhe um dos 6 temas. Cada tema pode ser escolhido por no máximo duas duplas.

3

Criação do repositório

Criem o repositório no GitHub agora — antes de escrever código. Nome sugerido: mini-projeto-poo.

4

Mãos na massa

Implementem o sistema. Usem o slide do tema como guia. O desafio extra é opcional mas conta pontos.

5

Entrega

Commit e push no GitHub antes de sair. O link do repositório deve ser enviado no canal da turma.

Atenção: ⚠️ Atenção: O repositório precisa ser criado hoje. Projetos sem commit até o final da próxima aula não serão aceitos.

mini projeto · dicas

Antes de codar — planeje

5 minutos de planejamento economizam 30 minutos de retrabalho.

Liste as classes

Quais objetos existem no seu sistema? Escreva no papel antes de abrir o VS Code.

Defina os atributos

O que cada objeto sabe? Quais precisam de proteção com @property?

Mapeie os relacionamentos

Quais objetos vivem dentro de outros (composição)? Quais são independentes (agregação)?

Implementem uma classe de cada vez. Testem antes de passar para a próxima.
próxima aula

Aula 7 · 29/04

Herança — parte 1

Com as bases sólidas, chegou a hora de reutilizar código de verdade. Vamos aprender como uma classe pode herdar atributos e comportamentos de outra.

class Filho(Pai) herança simples super() atributos herdados