Você foi contratada para desenvolver um sistema de pagamento que aceita diferentes formas de pagamento: cartão de crédito, boleto bancário e PIX.
a. Crie uma classe abstrata chamada Pagamento com:
a. Um atributo valor (float)
b. Um método abstrato processar_pagamento()
b. Crie três classes que herdam de Pagamento:
a. CartaoCredito: recebe também numero_cartao e nome_titular
b. Boleto: recebe também codigo_barras
c. Pix: recebe também chave_pix
c. Cada classe deve implementar o método processar_pagamento() com uma mensagem personalizada, como:
a. “Processando pagamento de R$100.00 via cartão de crédito para João.”
b. “Pagamento de \mathrm{R} \ 100.00$ via boleto com código 123456789 .”
c. “Pagamento de R$100.00 via PIX usando chave joao@email.com.”
d. No programa principal (main), crie uma lista com instâncias de cada tipo de pagamento e use um laço para chamar processar_pagamento() em cada uma.

Passo 1

O enunciado pede que eu implemente um sistema de pagamentos com as seguintes especificações: \n
  • Criar uma classe abstrata chamada Pagamento com um atributo valor (tipo float) e um método abstrato processar\_pagamento(). \n
  • Criar três classes que herdam de Pagamento: \n
    • CartaoCredito: além de valor, recebe numero\_cartao e nome\_titular. \n
    • Boleto: além de valor, recebe codigo\_barras. \n
    • Pix: além de valor, recebe chave\_pix. \n
  • Cada classe deve implementar processar\_pagamento() exibindo uma mensagem personalizada, por exemplo: \n
    • “Processando pagamento de R$100.00 via cartão de crédito para João.” \n
    • “Pagamento de R$100.00 via boleto com código 123456789.” \n
    • “Pagamento de R$100.00 via PIX usando chave joao@email.com.” \n
  • No programa principal, criar uma lista com instâncias de cada tipo e iterar chamando processar\_pagamento() em cada uma.
As informações relevantes que eu tenho: \n
  • O atributo comum entre os tipos é valor (um número real). \n
  • Há diferenciação por atributos extras conforme o tipo de pagamento. \n
  • O comportamento obrigatório é implementar o método processar\_pagamento() com mensagens diferentes. \n
  • Resultado esperado: ao rodar o programa, veremos as mensagens de processamento para cada instância.

Passo 2

Breve explicação didática (o que é preciso saber antes de codificar): \n
  • Classe abstrata: é uma classe que serve como “modelo” e não deve ser instanciada diretamente. Em Python usamos o módulo abc e fazemos a classe herdar de ABC. Métodos marcados com o decorator @abstractmethod obrigam as classes filhas a implementá-los. \n
    • Por que usar? Porque todos os pagamentos têm valor e um processar\_pagamento(), mas a implementação varia. Colocar isso numa classe abstrata força consistência. \n
  • Herança: classes-filhas reutilizam atributos e métodos da classe-pai e podem sobrescrever (override) métodos para comportamento específico. \n
  • Formatar número para moeda: ao exibir valor queremos mostrar com duas casas decimais. Em Python usamos formatação como f"{valor:.2f}" para obter sempre duas casas decimais (por ex.: 100{,}00 vira “100.00” no padrão Python). \n
    Exemplo simples em palavras: se eu tenho valor=100, com f"{valor:.2f}" será mostrado “100.00”.

Passo 3

Vou mostrar a estrutura da classe abstrata Pagamento e explicar linha a linha (exemplo em Python): \n
Código (explicado depois):\n
from abc import ABC, abstractmethod

class Pagamento(ABC):
    def __init__(self, valor: float):
        # armazeno o valor como float para garantir operações numéricas corretas
        self.valor = float(valor)

    @abstractmethod
    def processar_pagamento(self):
        pass
Explicação passo a passo: \n
  • from abc import ABC, abstractmethod: importa ferramentas para criar classes abstratas. \n
  • class Pagamento(ABC):: define a classe abstrata que não será instanciada diretamente. \n
  • def __init__(self, valor: float):: construtor que recebe valor. Anote que valor é o atributo comum. Convertemos com float(valor) para ter garantia de tipo. \n
  • @abstractmethod e def processar_pagamento(self):: marca que qualquer subclasse deve implementar esse método. Sem isso, a subclasse também seria abstrata e não poderia ser instanciada.

Passo 4

Agora criamos a classe CartaoCredito e explico o que cada parte faz: \n
Código (explicado depois):\n
class CartaoCredito(Pagamento):
    def __init__(self, valor: float, numero_cartao: str, nome_titular: str):
        super().__init__(valor)
        self.numero_cartao = numero_cartao
        self.nome_titular = nome_titular

    def processar_pagamento(self):
        print(f"Processando pagamento de R${self.valor:.2f} via cartão de crédito para {self.nome_titular}.")
Explicação: \n
  • class CartaoCredito(Pagamento): declara que herda de Pagamento. \n
  • No construtor, super().__init__(valor) chama o construtor da classe-pai para definir self.valor. Isso evita repetir código. \n
  • Armazenamos numero_cartao e nome_titular como atributos específicos desse tipo. \n
  • processar_pagamento é a implementação obrigatória do método abstrato. A mensagem usa f-string para inserir o valor formatado com duas casas decimais e o nome do titular.

Passo 5

Agora a classe Boleto (código e explicação): \n
Código:\n
class Boleto(Pagamento):
    def __init__(self, valor: float, codigo_barras: str):
        super().__init__(valor)
        self.codigo_barras = codigo_barras

    def processar_pagamento(self):
        print(f"Pagamento de R${self.valor:.2f} via boleto com código {self.codigo_barras}.")
Explicação: \n
  • A lógica é a mesma: herda valor do pai e adiciona codigo_barras. \n
  • A mensagem insere self.codigo_barras para mostrar qual boleto está sendo processado.

Passo 6

Agora a classe Pix (código e explicação): \n
Código:\n
class Pix(Pagamento):
    def __init__(self, valor: float, chave_pix: str):
        super().__init__(valor)
        self.chave_pix = chave_pix

    def processar_pagamento(self):
        print(f"Pagamento de R${self.valor:.2f} via PIX usando chave {self.chave_pix}.")
Explicação: \n
  • Igual aos anteriores: guarda chave_pix e mostra na mensagem ao processar.

Passo 7

Agora monto o programa principal ( main), crio instâncias e itero sobre elas. Vou explicar por que fazer assim: \n
  • Coloco cada instância numa lista porque isso permite tratar diferentes tipos de pagamento de forma uniforme (polimorfismo): ao chamar processar_pagamento() em cada objeto, a implementação correta de cada classe será executada. \n
    Código completo do programa (juntando tudo):\n
from abc import ABC, abstractmethod

class Pagamento(ABC):
    def __init__(self, valor: float):
        self.valor = float(valor)

    @abstractmethod
    def processar_pagamento(self):
        pass

class CartaoCredito(Pagamento):
    def __init__(self, valor: float, numero_cartao: str, nome_titular: str):
        super().__init__(valor)
        self.numero_cartao = numero_cartao
        self.nome_titular = nome_titular

    def processar_pagamento(self):
        print(f"Processando pagamento de R${self.valor:.2f} via cartão de crédito para {self.nome_titular}.")

class Boleto(Pagamento):
    def __init__(self, valor: float, codigo_barras: str):
        super().__init__(valor)
        self.codigo_barras = codigo_barras

    def processar_pagamento(self):
        print(f"Pagamento de R${self.valor:.2f} via boleto com código {self.codigo_barras}.")

class Pix(Pagamento):
    def __init__(self, valor: float, chave_pix: str):
        super().__init__(valor)
        self.chave_pix = chave_pix

    def processar_pagamento(self):
        print(f"Pagamento de R${self.valor:.2f} via PIX usando chave {self.chave_pix}.")

if __name__ == "__main__":
    # crio instâncias de exemplo
    p1 = CartaoCredito(100.00, "1111-2222-3333-4444", "João")
    p2 = Boleto(100.00, "123456789")
    p3 = Pix(100.00, "joao@email.com")

    pagamentos = [p1, p2, p3]

    for p in pagamentos:
        p.processar_pagamento()
Comentários práticos: \n
  • if __name__ == "__main__": permite que o código seja importado como módulo sem executar o bloco de teste automaticamente. \n
  • Os valores 100.00 no exemplo são apenas ilustrativos; em um sistema real viriam de input do usuário ou de outra parte do sistema. \n
  • Ao executar este script em Python, cada chamada a processar_pagamento() exibirá a mensagem correspondente ao tipo do objeto.

Passo 8

Dicas para a hora da prova (resumo prático e rápido): \n
  • Lembre-se: criar a classe abstrata com ABC e @abstractmethod quando você quer garantir assinatura comum e obrigar implementação nas filhas. \n
  • Use super().__init__(...) para reaproveitar inicialização do pai. \n
  • Use f"{valor:.2f}" para formatar números com duas casas decimais. \n
  • Para testar rapidamente, crie uma lista com instâncias diferentes e faça um for chamando o método comum — é o exemplo mais simples de polimorfismo.

Resposta

Processando pagamento de R$100.00 via cartão de crédito para João.
Pagamento de R$100.00 via boleto com código 123456789.
Pagamento de R$100.00 via PIX usando chave joao@email.com.

Exercícios relacionados