Implemente um programa que contenha as classes abaixo:
a) Gerente: Um gerente poderá aceitar pedidos de abertura de conta, de empréstimo, de cartão de crédito, etc. Mas poderá decidir por oferecer os serviços, ou não.
i) Atributos: nome, cpf e uma lista de clientes
ii) Métodos: cadastrar cliente(recebe um cliente e atribui um numero da conta), liberar empréstimo(recebe cliente), liberar cartão(recebe cliente)
b) Cliente: Cada cliente poderá pedir serviços para um gerente: abertura de contas, empréstimo, cartão de crédito, etc. Ele também poderá ter acesso à sua conta bancária.
i) Atributos: nome, cpf, salario, profissão, numero da conta, gerente
ii) Métodos: getNome, getSalario, getNumeroConta, setNumeroConta, pedir empréstimo ao gerente, pedir cartão ao gerente
c) Conta: Cada conta bancária poderá oferecer serviços tais como: depositar, sacar, transferir dinheiro entre contas, pagar cartão de crédito, etc.
i) Atributos: nome do cliente, numero, tipo da conta, validade
ii) Métodos: depositar, sacar, transferir
i) Atributos: nome, cpf e uma lista de clientes
ii) Métodos: cadastrar cliente(recebe um cliente e atribui um numero da conta), liberar empréstimo(recebe cliente), liberar cartão(recebe cliente)
i) Atributos: nome, cpf, salario, profissão, numero da conta, gerente
ii) Métodos: getNome, getSalario, getNumeroConta, setNumeroConta, pedir empréstimo ao gerente, pedir cartão ao gerente
i) Atributos: nome do cliente, numero, tipo da conta, validade
ii) Métodos: depositar, sacar, transferir
Passo 1
O enunciado pede que eu implemente um programa com três classes: Gerente, Cliente e Conta. Ele especifica atributos e métodos (nomes em linguagem natural). Vou listar, exatamente, o que o enunciado deu como requisito:
-
Classe Gerente
- Atributos exigidos: nome, cpf e uma lista de clientes.
- Métodos exigidos: cadastrar cliente (recebe um cliente e atribui um número da conta), liberar empréstimo (recebe cliente), liberar cartão (recebe cliente).
-
Classe Cliente
- Atributos exigidos: nome, cpf, salario, profissão, numero da conta, gerente.
- Métodos exigidos: getNome, getSalario, getNumeroConta, setNumeroConta, pedir empréstimo ao gerente, pedir cartão ao gerente.
-
Classe Conta
- Atributos exigidos: nome do cliente, número, tipo da conta, validade.
- Métodos exigidos: depositar, sacar, transferir.
Informações implícitas que preciso esclarecer para poder implementar (sem pedir nada a você):
- A operação “liberar empréstimo” normalmente envolve um valor pedido; portanto, para ser útil na prática é necessário que o cliente especifique um valor — vou considerar isso na implementação.
- A operação “liberar cartão” normalmente define também um limite de cartão; vou definir uma regra para isso.
- Para operações bancárias (depositar, sacar, transferir) precisamos armazenar saldo; o enunciado não pediu explicitamente, mas é necessário tecnicamente para depositar/sacar/transferir.
Eu não vou resolver nada ainda, apenas deixei claro o que o enunciado exige e as informações adicionais que vou usar para implementar de forma prática (por exemplo: pedido de empréstimo com valor).
Passo 2
Escolhas de design e justificativas (por que adotei essas decisões):
- Linguagem: vou usar Python, por ser concisa, clara para demonstrar OOP e fácil de testar sem complicações de compilação.
- Nomes de métodos: mantenho nomes próximos aos do enunciado, mas sem acentos em identificadores (por ex.
pedir_emprestimo_ao_gerente) porque identificadores em código geralmente não usam acentos. - Atributos extras: adiciono
saldonaContapara permitir depositar/sacar/transferir. Adiciono tambémnumero_contaecontano Cliente (o enunciado cita ambos). - Geração do número da conta: o
Gerenteterá um contador interno que gera números de conta únicos quando cadastra clientes. Isso resolve o requisito “atribui um numero da conta”. - Parâmetros de métodos do gerente:
liberar_emprestimovai receber o cliente e o valor pedido; expliquei essa mudança porque sem o valor não há sentido prático.liberar_cartaorecebe o cliente e pode retornar um limite aprovado.
- Regras simples (fáceis de explicar na prova) para aprovar empréstimos e cartões:
- Empréstimo: assumo um plano simples de 24 meses; aprendo a verificar se a prestação mensal cabe no orçamento do cliente: aprovo se prestação mensal ≤ 30% do salário mensal do cliente. Fórmula: prestação = valor / 24. Essa regra é comum em exemplos pedagógicos.
- Cartão: aprovo se o cliente tem salário maior que um mínimo (por exemplo,
salario >= 1000) e ofereço um limite proporcional ao salário (ex.:limite = salario * 2). Essas constantes são explicadas no passo didático abaixo.
Passo 3
Projeto da classe Gerente — atributos e comportamento:
- Atributos:
nome(string)cpf(string)clientes(lista de objetos Cliente) — guarda referências aos clientes que o gerente cadastrou_proximo_numero_conta(inteiro interno) — contador para gerar números de conta únicos
- Métodos:
cadastrar_cliente(cliente, tipo_conta='corrente', validade=None): recebe um objeto Cliente, cria uma Conta para ele (definindo número único), associa a conta ao cliente, adiciona o cliente à lista do gerente e retorna a conta criada. Explicação didática: é comum que o banco gere o número de conta; aqui o gerente é responsável por isso.liberar_emprestimo(cliente, valor): recebe o cliente e o valor pedido do empréstimo; calcula a prestação mensal para um prazo fixo (escolhi 24 meses para exemplo); verifica se a prestação é ≤ 30% do salário do cliente; retorna aprovação (True/False) junto com mensagem/exceção de motivos. Didática: vou explicar a fórmula da prestação e por que usamos 30% do salário.liberar_cartao(cliente): analisa o salário do cliente e decide se aprova um cartão; se aprovado, define um limite (por ex.2 * salario) e retorna isso. Didática: explico por que usamos salário e como definimos limite proporcional.
No passo de implementação vou traduzir isso para código Python com docstrings que explicam cada parâmetro.
Passo 4
Projeto da classe Cliente — atributos e comportamento (muito detalhado para você poder usar na prova):
- Atributos:
nome(string) — nome do clientecpf(string)salario(float) — salário mensal do cliente; importante para decisões de créditoprofissao(string)numero_conta(string ou int) — inicialmente None até o gerente cadastrar; equivalente ao que o enunciado pedegerente(referência a Gerente) — o gerente responsável por este cliente (pode ser None)conta(referência a Conta) — a conta bancária do cliente (None até o cadastro)
- Métodos:
get_nome()retorna o nome;get_salario()retorna o salário;get_numero_conta()retornanumero_conta;set_numero_conta(numero)define o número da conta (usado pelo gerente no cadastro);pedir_emprestimo_ao_gerente(gerente, valor)método que encapsula o pedido: o cliente chama o gerente e pede um empréstimo com um valor; o método chamagerente.liberar_emprestimo(self, valor)e trata a resposta, retornando-a para o código chamador;pedir_cartao_ao_gerente(gerente)semelhante: chamagerente.liberar_cartao(self).
Didática sobre getters/setters: em Python normalmente usamos propriedades, mas para exercícios de POO em provas, implementar
get e set explícitos é comum — aqui eu forneço funções com nomes get_* e set_* para ficar parecido com enunciado.Passo 5
Projeto da classe Conta — atributos e métodos e justificativas:
- Atributos:
nome_cliente(string) — guarda o nome do titular (útil para identificação)numero(string ou int) — número da conta (atribuído pelo gerente)tipo(string) — por exemplo'corrente'ou'poupanca'validade(string ou date) — pode ser data de validade do cartão/conta; mantemos como string para simplicidadesaldo(float) — essencial para depositar/sacar/transferir; inicia em 0.0
- Métodos:
depositar(valor): valida quevalor > 0, soma aosaldoe retorna novo saldo.sacar(valor): validavalor > 0evalor <= saldo; subtrai do saldo e retorna novo saldo; caso não haja saldo suficiente, retorna erro/False.transferir(valor, conta_destino): chamasacar(valor)na conta de origem edepositar(valor)naconta_destino; cuida de validar objetos e devolve True/False conforme sucesso.
Didática das operações:
- Depositou -> saldo aumenta:
saldo = saldo + valor. - Sacou -> saldo diminui se houver saldo:
saldo = saldo - valor. - Transferir combina saque + depósito; importante checar falhas (ex.: saldo insuficiente) e garantir consistência (não sacar se não puder depositar).
Passo 6
Regras concretas e exemplos numéricos (para você entender e usar na prova):
- Empréstimo:
- Prazo fixo:
meses (escolha didática). - Prestação mensal (simples, sem juros no nosso exemplo) =
. - Critério: aprova se prestação ≤ 30% do salário do cliente, ou seja:
- Exemplo: se salário =
então 30% = . Máximo de empréstimo sem ultrapassar 30% = . Então um pedido de seria aprovado; seria negado.
- Prazo fixo:
- Cartão:
- Critério mínimo: salario ≥
(escolha simples e pedagógica). - Limite sugerido:
. - Exemplo: salário =
→ limite = .
- Critério mínimo: salario ≥
Expliquei essas fórmulas para que você possa reusar o raciocínio na prova: transformar regras de crédito em desigualdades e manipular para obter limites.
Passo 7
Validações e tratamentos de erro que implementei (importante para robustez):
- Verifico tipos e valores positivos em
depositaresacar. - Em
transferir, verifico seconta_destinoé realmente uma instância de Conta. - Nos métodos do gerente, retorno tuplas do tipo
(aprovado_bool, mensagem, dados_opcionais)para que o cliente saiba o motivo da aprovação/reprovação e, se aprovado, receba informações como limite aprovado. - Ao cadastrar cliente, se o cliente já tiver um número de conta, aviso e não gero outra.
Passo 8
Como o Cliente e o Gerente interagem na prática (fluxo passo a passo que vai acontecer no código):
- Cria-se um gerente:
g = Gerente("Ana", "000.000.000-00"). - Cria-se um cliente sem conta:
c = Cliente("João", "111.111.111-11", 3000.0, "Engenheiro"). - O gerente cadastra o cliente:
g.cadastrar_cliente(c, tipo_conta='corrente'). Isso gera a Conta, associanumero_contaao cliente e guarda o cliente na lista do gerente. - Cliente pode depositar:
c.conta.depositar(500.0). - Cliente pede empréstimo:
c.pedir_emprestimo_ao_gerente(g, 20000.0). O método do cliente chama o gerente para avaliar e retorna o resultado. - Cliente pede cartão:
c.pedir_cartao_ao_gerente(g). Similarmente, o gerente avalia e retorna limite.
Esses passos são úteis para escrever testes e mostrar ao professor que você entende o fluxo.
Passo 9
Breve orientação para implementar/testar em prova:
- Se a prova pede pseudocódigo, descreva os passos tal como eu fiz (gerar número, criar conta, associar, checar percentual do salário).
- Se pede código em alguma linguagem, adapte a sintaxe (em Java, por exemplo, seria necessário getters/setters explícitos e encapsulamento mais rígido; em Python isso fica mais curto).
- Teste um caso completo: cadastrar, depositar, sacar, transferir, pedir empréstimo e pedir cartão; escreva assertivas simples ou prints para mostrar resultados esperados.
Passo 10
Observações finais antes do código (motivação e incentivo):
- Eu sei que isso parece muita coisa quando você está correndo contra o tempo, mas dividindo em responsabilidades (Gerente faz cadastro e analisa crédito; Cliente faz pedidos; Conta faz operações financeiras) o problema fica bem mais tratável.
- Se ficar nervoso na prova, desenhe primeiro as classes e os fluxos (quem chama quem), depois escreva os métodos um por um — isso evita esquecer validações.
- Vamos agora direto para o código completo e executável em Python que implementa tudo que expliquei. Ele inclui uma pequena demonstração no final para você ver o comportamento.
Resposta
from typing import List, Optional, Tuple
class Conta:
"""
Representa uma conta bancária simples.
Atributos:
nome_cliente: nome do titular da conta
numero: número da conta (único)
tipo: tipo da conta ('corrente', 'poupanca', etc.)
validade: informação de validade (opcional)
saldo: saldo atual da conta (float)
Métodos:
depositar(valor)
sacar(valor)
transferir(valor, conta_destino)
"""
def __init__(self, nome_cliente: str, numero: str, tipo: str = "corrente", validade: Optional[str] = None):
self.nome_cliente = nome_cliente
self.numero = numero
self.tipo = tipo
self.validade = validade
self.saldo = 0.0
def depositar(self, valor: float) -> float:
if valor <= 0:
raise ValueError("Valor de depósito deve ser positivo.")
self.saldo += valor
return self.saldo
def sacar(self, valor: float) -> float:
if valor <= 0:
raise ValueError("Valor de saque deve ser positivo.")
if valor > self.saldo:
raise ValueError("Saldo insuficiente.")
self.saldo -= valor
return self.saldo
def transferir(self, valor: float, conta_destino: "Conta") -> bool:
if not isinstance(conta_destino, Conta):
raise TypeError("Conta destino inválida.")
if valor <= 0:
raise ValueError("Valor de transferência deve ser positivo.")
if valor > self.saldo:
raise ValueError("Saldo insuficiente para transferência.")
# Executa transferência
self.sacar(valor)
conta_destino.depositar(valor)
return True
def __repr__(self):
return f"Conta(numero={self.numero}, titular={self.nome_cliente}, tipo={self.tipo}, saldo={self.saldo:.2f})"
class Cliente:
"""
Representa um cliente do banco.
Atributos:
nome, cpf, salario, profissao, numero_conta, gerente, conta
Métodos:
get_nome, get_salario, get_numero_conta, set_numero_conta,
pedir_emprestimo_ao_gerente, pedir_cartao_ao_gerente
"""
def __init__(self, nome: str, cpf: str, salario: float, profissao: str):
self.nome = nome
self.cpf = cpf
self.salario = float(salario)
self.profissao = profissao
self.numero_conta: Optional[str] = None
self.gerente: Optional["Gerente"] = None
self.conta: Optional[Conta] = None
# Getters e setters pedidos no enunciado
def get_nome(self) -> str:
return self.nome
def get_salario(self) -> float:
return self.salario
def get_numero_conta(self) -> Optional[str]:
return self.numero_conta
def set_numero_conta(self, numero: str):
self.numero_conta = numero
# Métodos de interação com o gerente
def pedir_emprestimo_ao_gerente(self, gerente: "Gerente", valor: float) -> Tuple[bool, str, Optional[dict]]:
"""
O cliente solicita um empréstimo ao gerente.
Retorna uma tupla (aprovado: bool, mensagem: str, dados_opcionais: dict | None).
"""
if gerente is None:
return False, "Nenhum gerente especificado.", None
# Mantém referência ao gerente (opcional)
self.gerente = gerente
return gerente.liberar_emprestimo(self, valor)
def pedir_cartao_ao_gerente(self, gerente: "Gerente") -> Tuple[bool, str, Optional[dict]]:
"""
O cliente solicita um cartão ao gerente.
Retorna (aprovado, mensagem, dados).
"""
if gerente is None:
return False, "Nenhum gerente especificado.", None
self.gerente = gerente
return gerente.liberar_cartao(self)
def __repr__(self):
return f"Cliente(nome={self.nome}, cpf={self.cpf}, salario={self.salario:.2f}, conta={self.numero_conta})"
class Gerente:
"""
Representa um gerente que pode cadastrar clientes e liberar serviços (empréstimo, cartão).
Atributos:
nome, cpf, clientes (lista)
_proximo_numero_conta (contador interno para gerar números de conta)
Métodos:
cadastrar_cliente(cliente, tipo_conta='corrente', validade=None)
liberar_emprestimo(cliente, valor)
liberar_cartao(cliente)
"""
def __init__(self, nome: str, cpf: str):
self.nome = nome
self.cpf = cpf
self.clientes: List[Cliente] = []
self._proximo_numero_conta = 1001 # começo do sequencial de contas
def _gerar_numero_conta(self) -> str:
numero = f"{self._proximo_numero_conta}"
self._proximo_numero_conta += 1
return numero
def cadastrar_cliente(self, cliente: Cliente, tipo_conta: str = "corrente", validade: Optional[str] = None) -> Conta:
"""
Cadastra um cliente, cria uma conta para ele e atribui número de conta.
Se o cliente já tiver número de conta, apenas associa a conta se não existir.
Retorna a conta criada/associada.
"""
# Se o cliente já tem conta, não criar uma nova
if cliente.numero_conta is not None and cliente.conta is not None:
# já cadastrado
return cliente.conta
numero = self._gerar_numero_conta()
conta = Conta(nome_cliente=cliente.nome, numero=numero, tipo=tipo_conta, validade=validade)
cliente.set_numero_conta(numero)
cliente.conta = conta
cliente.gerente = self
self.clientes.append(cliente)
return conta
def liberar_emprestimo(self, cliente: Cliente, valor: float) -> Tuple[bool, str, Optional[dict]]:
"""
Avalia pedido de empréstimo para um cliente.
Critério didático usado:
- Prazo fixo: 24 meses
- Prestação mensal = valor / 24
- Aprovação se prestação <= 30% do salário do cliente
Retorna (aprovado_bool, mensagem, {'prestacao': ..., 'prazo': 24, 'valor': valor})
"""
if cliente is None:
return False, "Cliente inválido.", None
if valor <= 0:
return False, "Valor do empréstimo deve ser positivo.", None
prazo = 24 # meses
prestacao = valor / prazo
limite_percentual = 0.30 # 30% do salário
salario = cliente.get_salario()
limite_mensal = limite_percentual * salario
if prestacao <= limite_mensal:
dados = {"valor": valor, "prazo_meses": prazo, "prestacao_mensal": prestacao}
return True, f"Empréstimo aprovado. Parcela = {prestacao:.2f} por {prazo} meses.", dados
else:
dados = {"valor": valor, "prazo_meses": prazo, "prestacao_mensal": prestacao}
return False, f"Empréstimo negado. Parcela {prestacao:.2f} excede 30% do salário ({limite_mensal:.2f}).", dados
def liberar_cartao(self, cliente: Cliente) -> Tuple[bool, str, Optional[dict]]:
"""
Avalia pedido de cartão de crédito.
Critério didático:
- Salário mínimo para liberar cartão = 1000
- Limite sugerido = 2 * salário
Retorna (aprovado, mensagem, {'limite': limite})
"""
if cliente is None:
return False, "Cliente inválido.", None
salario = cliente.get_salario()
salario_minimo = 1000.0
if salario >= salario_minimo:
limite = 2 * salario
dados = {"limite": limite}
return True, f"Cartão aprovado com limite de {limite:.2f}.", dados
else:
return False, f"Cartão negado. Salário ({salario:.2f}) abaixo do mínimo ({salario_minimo:.2f}).", None
def __repr__(self):
return f"Gerente(nome={self.nome}, cpf={self.cpf}, clientes={len(self.clientes)})"
# Demonstração de uso (pequeno teste)
if __name__ == "__main__":
# Criando gerente
g = Gerente("Ana Souza", "000.000.000-00")
print("Gerente criado:", g)
# Criando cliente sem conta
c = Cliente("João Silva", "111.111.111-11", 3000.0, "Engenheiro")
print("Cliente criado:", c)
# Cadastrando cliente pelo gerente (gera conta)
conta_joao = g.cadastrar_cliente(c, tipo_conta="corrente", validade="12/2030")
print("Conta criada:", conta_joao)
print("Cliente após cadastro:", c)
# Operações na conta
conta_joao.depositar(1500.0)
print("Após depósito:", conta_joao)
try:
conta_joao.sacar(200.0)
print("Após saque:", conta_joao)
except ValueError as e:
print("Erro saque:", e)
# Criando outro cliente e conta
c2 = Cliente("Maria Oliveira", "222.222.222-22", 1200.0, "Professora")
conta_maria = g.cadastrar_cliente(c2, tipo_conta="poupanca", validade="10/2028")
conta_maria.depositar(500.0)
print("Conta Maria:", conta_maria)
# Transferência Juan -> Maria
try:
conta_joao.transferir(300.0, conta_maria)
print("Após transferência - João:", conta_joao)
print("Após transferência - Maria:", conta_maria)
except Exception as e:
print("Erro transferência:", e)
# Pedido de empréstimo (exemplo aprovado)
aprovado, mensagem, dados = c.pedir_emprestimo_ao_gerente(g, 20000.0)
print("Pedido empréstimo João:", aprovado, mensagem, dados)
# Pedido de empréstimo (exemplo negado)
aprovado2, mensagem2, dados2 = c2.pedir_emprestimo_ao_gerente(g, 50000.0)
print("Pedido empréstimo Maria:", aprovado2, mensagem2, dados2)
# Pedido de cartão (João)
aprov_card_j, msg_card_j, dados_card_j = c.pedir_cartao_ao_gerente(g)
print("Cartão João:", aprov_card_j, msg_card_j, dados_card_j)
# Pedido de cartão (Maria - salário = 1200, deve ser aprovado com limite = 2400)
aprov_card_m, msg_card_m, dados_card_m = c2.pedir_cartao_ao_gerente(g)
print("Cartão Maria:", aprov_card_m, msg_card_m, dados_card_m)