Desafio PHP
Múltiplos catch e exceções encadeadas
Enunciado
Crie duas exceções personalizadas: SaldoInsuficienteException e ValorInvalidoException, ambas estendendo Exception. Implemente uma classe ContaBancaria com saldo inicial e método sacar($valor). O método deve lançar ValorInvalidoException se $valor <= 0 e SaldoInsuficienteException se $valor > saldo. No código principal, realize três saques: -50, 200 (saldo inicial 100) e 50. Use um único bloco try com múltiplos catch para tratar cada exceção e um finally que imprime "Operação finalizada" após cada tentativa (dica: use um laço ou repita o try/catch).
Requisitos
- As classes
SaldoInsuficienteExceptioneValorInvalidoExceptiondevem estenderException. - O método
sacardeve lançar as exceções conforme as condições. - O código principal deve ter múltiplos
catchpara cada tipo de exceção. - O
finallydeve ser executado após cada tentativa de saque. - A saída deve mostrar as mensagens de erro e o saldo final após o saque bem-sucedido.
Código inicial
<?php
// Defina as exceções personalizadas
class ContaBancaria {
private $saldo;
public function __construct($saldoInicial) {
$this->saldo = $saldoInicial;
}
public function sacar($valor) {
// Lance as exceções apropriadas
// Atualize o saldo se o saque for válido
}
public function getSaldo() {
return $this->saldo;
}
}
// Crie uma conta com saldo 100
// Realize os saques -50, 200, 50 usando try/catch/finally
Saída esperada
Valor inválido: -50
Operação finalizada
Saldo insuficiente: 200 (saldo atual: 100)
Operação finalizada
Saque de 50 realizado. Novo saldo: 50
Operação finalizada
Ver dica
Use um array com os valores de saque e um laço foreach para repetir o bloco try/catch/finally. No catch, capture cada exceção específica e imprima a mensagem.
Mostrar solução
<?php
class SaldoInsuficienteException extends Exception {}
class ValorInvalidoException extends Exception {}
class ContaBancaria {
private $saldo;
public function __construct($saldoInicial) {
$this->saldo = $saldoInicial;
}
public function sacar($valor) {
if ($valor <= 0) {
throw new ValorInvalidoException("Valor inválido: $valor");
}
if ($valor > $this->saldo) {
throw new SaldoInsuficienteException("Saldo insuficiente: $valor (saldo atual: {$this->saldo})");
}
$this->saldo -= $valor;
echo "Saque de $valor realizado. Novo saldo: {$this->saldo}\n";
}
public function getSaldo() {
return $this->saldo;
}
}
$conta = new ContaBancaria(100);
$saques = [-50, 200, 50];
foreach ($saques as $valor) {
try {
$conta->sacar($valor);
} catch (ValorInvalidoException $e) {
echo $e->getMessage() . "\n";
} catch (SaldoInsuficienteException $e) {
echo $e->getMessage() . "\n";
} finally {
echo "Operação finalizada\n";
}
}
Passo a passo
- Definimos duas exceções personalizadas que estendem
Exception. - A classe
ContaBancariatem um saldo privado e um métodosacar. - No
sacar, verificamos primeiro se o valor é inválido (<= 0) e lançamosValorInvalidoException. - Depois, verificamos se o valor excede o saldo e lançamos
SaldoInsuficienteException. - Se passar, subtraímos do saldo e imprimimos a mensagem de sucesso.
- No código principal, criamos uma conta com saldo 100 e um array de saques.
- Para cada saque, usamos
trypara chamarsacar, comcatchpara cada tipo de exceção efinallypara imprimir "Operação finalizada".
Por que funciona
O uso de múltiplos catch permite tratar cada exceção de forma específica. O finally é executado após cada iteração, independentemente de erro. O laço repete o bloco para cada valor, simulando tentativas sequenciais.
Erros comuns
- Ordem dos
catch: se capturarExceptionantes das específicas, as específicas nunca serão alcançadas. Sempre do mais específico para o mais genérico. - Esquecer de atualizar o saldo: se não fizer
$this->saldo -= $valor, o saldo não muda. - Lançar exceção com tipo errado: por exemplo, lançar
Exceptiongenérica em vez das personalizadas, o que impediria a captura específica.
Outra forma de resolver
Você pode usar um único catch (Throwable $e) e verificar o tipo com instanceof, mas múltiplos catch são mais limpos e idiomáticos.
Saída esperada
Valor inválido: -50
Operação finalizada
Saldo insuficiente: 200 (saldo atual: 100)
Operação finalizada
Saque de 50 realizado. Novo saldo: 50
Operação finalizada