Банковская система
Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy — урок 89 из 91.
Задание
ЛегкоДавайте создадим Банковскую систему, которая обрабатывает счета, транзакции и переводы между счетами. Вы создадите систему с надлежащей инкапсуляцией для защиты финансовых данных, наследованием для различных типов счетов и валидацией для обеспечения целостности данных.
Вы организуете свой код в шести файлах:
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— возвращает счет или nulltransfer(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 знака после запятой)
?>Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово $thisМетодыСвойстваКонструктор (__construct)Деструктор (__destruct)Итоги — Простой калькулятор4Наследование
Основы наследованияКлючевое слово parent::Переопределение методовКлючевое слово finalАбстрактные классыИтоги — Иерархия сотрудников7Инкапсуляция
Public, Protected, PrivateПодробный разбор модификаторов доступаГеттеры и сеттерыСокрытие данныхConstructor Promotion (8.0)Итоги — Система учета студентов10Продвинутые концепции ООП
Композиция против наследованияВнедрение зависимостейАнонимные классыПеречисления (PHP 8.1)Файберы (PHP 8.1)Глубокое погружение в клонирование объектовГенераторы и итераторы13Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий2Пространства имен и автозагрузка
Введение в пространства именКлючевое слово useСтандарт автозагрузки PSR-4Автозагрузчик ComposerИтоги: структурированный проект5Интерфейсы и контракты
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовИнтерфейс против абстрактного классаType Hinting с интерфейсамиИтоги — Калькулятор фигур8Магические методы
Введение в магические методы__toString и __debugInfo__get, __set, __isset, __unset__call и __callStatic__clone и клонирование объектов__serialize и __unserializeИтоги — Кастомная коллекция11Система типов и обработка ошибок
Объявление типовNullable-типыТипы объединения и пересеченияКлассы исключенийИерархия пользовательских исключенийTry, Catch, FinallyИтоги — Валидатор форм14Проект: Управление библиотекой
Обзор проектаКлассы Book и User3Свойства классов
Свойства экземпляра и статические свойстваКонстанты в классахСтатические методы и свойстваПриватные и защищенные свойстваСвойства Readonly (PHP 8.1)Итоги — Менеджер банковского счета6Полиморфизм
Снова о переопределении методовПолиморфизм через интерфейсыType Hinting и Union TypesПозднее статическое связываниеИтоги — Payment Processor9Трейты
Введение в трейтыИспользование нескольких трейтовРазрешение конфликтов трейтовАбстрактные методы в трейтахТрейты и наследование12Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy15Финальные испытания
Платформа онлайн-обученияБанковская системаРазработка игрового персонажаСервис аренды транспорта