Menu
Coddy logo textTech

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

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

challenge icon

Задание

Легко

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

Вы распределите код по шести файлам:

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

    Формат JSON для account:

    [{"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"}]

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

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

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

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

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

<?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
// Для каждого account в $accounts:
//   - Если type равен "savings", создать SavingsAccount
//   - Если type равен "checking", создать CheckingAccount (с overdraft, если указан)
//   - Добавить account в bank
//   - Внести начальную сумму

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

?>

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

Потренируйтесь самостоятельно: Онлайн-компилятор PHP