Menu
Coddy logo textTech

Банковская система

Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy — урок 89 из 91.

challenge icon

Задание

Легко

Давайте создадим Банковскую систему, которая обрабатывает счета, транзакции и переводы между счетами. Вы создадите систему с надлежащей инкапсуляцией для защиты финансовых данных, наследованием для различных типов счетов и валидацией для обеспечения целостности данных.

Вы организуете свой код в шести файлах:

  • Transaction.php — Создайте класс Transaction для записи финансовых операций. Используйте продвижение свойств в конструкторе (constructor promotion) для type (string — "deposit", "withdrawal" или "transfer"), amount (float) и timestamp (string). Все свойства должны быть public readonly. Добавьте метод getDescription(): string, который возвращает "[type]: $[amount]" (отформатируйте сумму до 2 знаков после запятой).
  • BankAccount.php — Подключите файл Transaction. Создайте абстрактный класс BankAccount с:
    • Продвижением свойств в конструкторе для accountNumber (string, public readonly) и holderName (string, public readonly)
    • Защищенным свойством $balance, инициализированным значением 0.0
    • Приватным массивом для хранения истории транзакций
    • getBalance(): float — возвращает текущий баланс
    • deposit(float $amount): string — добавляет сумму к балансу, записывает транзакцию, возвращает "Deposited: $[amount]"
    • abstract withdraw(float $amount): string — дочерние классы реализуют правила снятия средств
    • addTransaction(Transaction $t): void — защищенный метод для добавления транзакций в историю
    • getTransactionCount(): int — возвращает количество транзакций
  • SavingsAccount.php — Подключите файл BankAccount. Создайте класс SavingsAccount, наследующий BankAccount, с:
    • Константой класса INTEREST_RATE, установленной в 0.02 (2%)
    • withdraw(float $amount): string — если сумма превышает баланс, возвращает "Insufficient funds"; в противном случае вычитает сумму, записывает транзакцию, возвращает "Withdrew: $[amount]"
    • applyInterest(): string — рассчитывает проценты на текущий баланс, добавляет их как депозит, возвращает "Interest applied: $[interest]"
  • CheckingAccount.php — Подключите файл BankAccount. Создайте класс CheckingAccount, наследующий BankAccount, с:
    • Приватным свойством $overdraftLimit, устанавливаемым через конструктор (добавьте третий параметр со значением по умолчанию 100.0)
    • withdraw(float $amount): string — позволяет снять средства, если сумма не превышает баланс + лимит овердрафта; возвращает "Insufficient funds (overdraft limit: $[limit])" в случае неудачи или "Withdrew: $[amount]" в случае успеха
    • getOverdraftLimit(): float — возвращает лимит овердрафта
  • Bank.php — Подключите оба файла аккаунтов. Создайте класс Bank, который управляет счетами:
    • Приватный массив для хранения счетов, индексированный по номеру счета
    • addAccount(BankAccount $account): void — добавляет счет
    • findAccount(string $accountNumber): ?BankAccount — возвращает счет или null
    • transfer(string $fromAccount, string $toAccount, float $amount): string — переводит деньги между счетами. Возвращает "Source account not found", "Destination account not found" или результат снятия средств, если оно не удалось. В случае успеха вносит депозит на целевой счет и возвращает "Transferred $[amount] from [from] to [to]"
  • main.php — Подключите файл Bank. Вы получите два входных значения: данные о счетах (JSON) и операции (JSON).

    Формат JSON для счетов:

    [{"type": "savings", "number": "SAV001", "holder": "Alice", "initial": 1000}, {"type": "checking", "number": "CHK001", "holder": "Bob", "initial": 500, "overdraft": 200}]

    Формат JSON для операций:

    [{"op": "deposit", "account": "SAV001", "amount": 200}, {"op": "withdraw", "account": "CHK001", "amount": 600}, {"op": "transfer", "from": "SAV001", "to": "CHK001", "amount": 300}, {"op": "interest", "account": "SAV001"}, {"op": "balance", "account": "SAV001"}]

    Создайте банк и все счета (внеся начальные суммы). Обработайте каждую операцию:

    • "deposit" — Выведите результат deposit()
    • "withdraw" — Выведите результат withdraw()
    • "transfer" — Выведите результат transfer()
    • "interest" — Выведите результат applyInterest() (только для сберегательных счетов)
    • "balance" — Выведите "[holder] balance: $[balance]" (2 знака после запятой)

    Выводите каждый результат на новой строке. Форматируйте все денежные суммы до 2 знаков после запятой.

Помните, что переводы должны быть атомарными — если снятие средств не удалось, депозит не должен произойти. Защищенное свойство $balance позволяет дочерним классам изменять его, сохраняя его скрытым от внешнего кода, что демонстрирует правильную инкапсуляцию в финансовом контексте.

Попробуйте сами

<?php

require_once 'Bank.php';

// Чтение входных данных
$accountsJson = trim(fgets(STDIN));
$operationsJson = trim(fgets(STDIN));

// Разбор JSON-входов
$accounts = (array)json_decode($accountsJson, true);
$operations = (array)json_decode($operationsJson, true);

// TODO: Создать экземпляр Bank

// TODO: Создать счета на основе данных об аккаунтах
// Для каждого счета в $accounts:
//   - Если тип "savings", создать SavingsAccount
//   - Если тип "checking", создать CheckingAccount (с овердрафтом, если он указан)
//   - Добавить счет в банк
//   - Внести начальную сумму

// TODO: Обработать каждую операцию
// Для каждой операции в $operations:
//   - "deposit": Вывести результат deposit()
//   - "withdraw": Вывести результат withdraw()
//   - "transfer": Вывести результат transfer()
//   - "interest": Вывести результат applyInterest() (только для сберегательных счетов)
//   - "balance": Вывести "[holder] balance: $[balance]" (2 знака после запятой)

?>

Все уроки раздела Объектно-ориентированное программирование