System bankowy
Część sekcji Programowanie obiektowe ścieżki PHP w Coddy. Lekcja 89 z 91.
Wyzwanie
ŁatwyZbudujmy system bankowy, który obsługuje konta, transakcje i przelewy między kontami. Stworzysz system z odpowiednią enkapsulacją, aby chronić dane finansowe, dziedziczeniem dla różnych typów kont oraz walidacją zapewniającą integralność danych.
Rozmieścisz kod w sześciu plikach:
Transaction.php: Utwórz klasęTransactiondo rejestrowania operacji finansowych. Użyj promocji konstruktora dlatype(string: "deposit", "withdrawal" lub "transfer"),amount(float) itimestamp(string). Wszystkie właściwości powinny być publiczne i tylko do odczytu. Dodaj metodęgetDescription(): string, która zwraca"[type]: $[amount]"(sformatuj kwotę do 2 miejsc po przecinku).BankAccount.php: Dołącz plik Transaction. Utwórz abstrakcyjną klasęBankAccountzawierającą:- Promocję konstruktora dla
accountNumber(string, public readonly) iholderName(string, public readonly) - Chronioną właściwość
$balancezainicjalizowaną wartością 0.0 - Prywatną tablicę do przechowywania historii transakcji
getBalance(): float: zwraca bieżące saldodeposit(float $amount): string: dodaje kwotę do salda, rejestruje transakcję i zwraca"Deposited: $[amount]"abstract withdraw(float $amount): string: klasy potomne implementują zasady wypłataddTransaction(Transaction $t): void: chroniona metoda dodająca transakcje do historiigetTransactionCount(): int: zwraca liczbę transakcji
- Promocję konstruktora dla
SavingsAccount.php: Dołącz plik BankAccount. Utwórz klasęSavingsAccountrozszerzającąBankAccount, która zawiera:- Stałą klasową
INTEREST_RATEustawioną na 0.02 (2%) withdraw(float $amount): string: jeśli kwota przekracza saldo, zwróć"Insufficient funds"; w przeciwnym razie odejmij kwotę, zarejestruj transakcję i zwróć"Withdrew: $[amount]"applyInterest(): string: oblicza odsetki od bieżącego salda, dodaje je jako wpłatę i zwraca"Interest applied: $[interest]"
- Stałą klasową
CheckingAccount.php: Dołącz plik BankAccount. Utwórz klasęCheckingAccountrozszerzającąBankAccount, która zawiera:- Prywatną właściwość
$overdraftLimitustawianą przez konstruktor (dodaj trzeci parametr o domyślnej wartości 100.0) withdraw(float $amount): string: pozwala na wypłatę, jeśli kwota nie przekracza sumy salda i limitu kredytu w rachunku; w przypadku niepowodzenia zwraca"Insufficient funds (overdraft limit: $[limit])", a w przypadku powodzenia"Withdrew: $[amount]"getOverdraftLimit(): float: zwraca limit kredytu w rachunku
- Prywatną właściwość
Bank.php: Dołącz oba pliki kont. Utwórz klasęBankdo zarządzania kontami:- Prywatna tablica do przechowywania kont indeksowanych numerem konta
addAccount(BankAccount $account): void: dodaje kontofindAccount(string $accountNumber): ?BankAccount: zwraca konto albo nulltransfer(string $fromAccount, string $toAccount, float $amount): string: przelewa pieniądze między kontami. Zwraca"Source account not found","Destination account not found"albo wynik wypłaty, jeśli się nie powiedzie. W przypadku powodzenia wpłaca środki na konto docelowe i zwraca"Transferred $[amount] from [from] to [to]"
main.php: Dołącz plik Bank. Otrzymasz dwa wejścia: dane kont (JSON) i operacje (JSON).Format JSON kont:
[{"type": "savings", "number": "SAV001", "holder": "Alice", "initial": 1000}, {"type": "checking", "number": "CHK001", "holder": "Bob", "initial": 500, "overdraft": 200}]Format JSON operacji:
[{"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"}]Utwórz bank i wszystkie konta (wpłacając kwoty początkowe). Przetwórz każdą operację:
"deposit": wypisz wynikdeposit()"withdraw": wypisz wynikwithdraw()"transfer": wypisz wyniktransfer()"interest": wypisz wynikapplyInterest()(tylko dla kont oszczędnościowych)"balance": wypisz"[holder] balance: $[balance]"(2 miejsca po przecinku)
Wypisz każdy wynik w nowej linii. Formatuj wszystkie kwoty pieniężne do 2 miejsc po przecinku.
Pamiętaj, że przelewy powinny być atomowe: jeśli wypłata się nie powiedzie, wpłata nie powinna nastąpić. Chroniona właściwość $balance pozwala klasom potomnym ją modyfikować, jednocześnie ukrywając ją przed kodem zewnętrznym, co pokazuje prawidłową enkapsulację w kontekście finansowym.
Spróbuj swoich sił
<?php
require_once 'Bank.php';
// Odczytaj dane wejściowe
$accountsJson = trim(fgets(STDIN));
$operationsJson = trim(fgets(STDIN));
// Przetwórz dane wejściowe w formacie JSON
$accounts = (array)json_decode($accountsJson, true);
$operations = (array)json_decode($operationsJson, true);
// TODO: Utwórz instancję Bank
// TODO: Utwórz konta na podstawie danych kont
// Dla każdego konta w $accounts:
// - Jeśli typ to "savings", utwórz SavingsAccount
// - Jeśli typ to "checking", utwórz CheckingAccount (z limitem debetowym, jeśli podano)
// - Dodaj konto do banku
// - Wpłać kwotę początkową
// TODO: Przetwórz każdą operację
// Dla każdej operacji w $operations:
// - "deposit": Wypisz wynik deposit()
// - "withdraw": Wypisz wynik withdraw()
// - "transfer": Wypisz wynik transfer()
// - "interest": Wypisz wynik applyInterest() (tylko dla kont oszczędnościowych)
// - "balance": Wypisz "[holder] balance: $[balance]" (2 miejsca po przecinku)
?>Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe $thisMetodyWłaściwościKonstruktor (__construct)Destruktor (__destruct)Powtórka — prosty kalkulator4Dziedziczenie
Podstawy dziedziczeniaSłowo kluczowe parent::Przesłanianie metodSłowo kluczowe finalKlasy abstrakcyjnePowtórzenie – hierarchia pracowników7Enkapsulacja
Public, protected, privateModyfikatory dostępu w szczegółachGettery i setteryUkrywanie informacjiPromocja parametrów konstruktora (8.0)Podsumowanie — system ewidencji studentów2Przestrzenie nazw i autoloading
Wprowadzenie do przestrzeni nazwSłowo kluczowe useStandard autoloadingu PSR-4Autoloader ComposeraPodsumowanie – uporządkowany projekt5Interfejsy i kontrakty
Wprowadzenie do interfejsówImplementowanie interfejsówImplementowanie wielu interfejsówInterfejs a klasa abstrakcyjnaPodpowiadanie typów za pomocą interfejsówPodsumowanie — kalkulator kształtów8Metody magiczne
Wprowadzenie do metod magicznych__toString i __debugInfo__get, __set, __isset, __unset__call i __callStatic__clone i klonowanie obiektów__serialize i __unserializePodsumowanie — własna kolekcja11System typów i obsługa błędów
Deklaracje typówTypy nullableTypy sumy i przecięciaKlasy wyjątkówNiestandardowa hierarchia wyjątkówTry, Catch, FinallyPodsumowanie — walidator formularzy14Projekt: Zarządzanie biblioteką
Przegląd projektuKlasy książki i użytkownika3Właściwości klas
Właściwości instancji a właściwości statyczneStałe w klasachMetody i właściwości statyczneWłaściwości prywatne i chronioneWłaściwości tylko do odczytu (PHP 8.1)Podsumowanie — menedżer kont bankowych6Polimorfizm
Ponowne omówienie nadpisywania metodPolimorfizm za pomocą interfejsówPodpowiedzi typów i typy sumyPóźne wiązanie statycznePodsumowanie — procesor płatności9Cechy
Wprowadzenie do cechKorzystanie z wielu cechRozwiązywanie konfliktów cechMetody abstrakcyjne w cechachCechy a dziedziczenie12Wzorce projektowe, część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec Strategy15Wyzwania końcowe
Platforma e-learningowaSystem bankowyTworzenie postaci do gryUsługa wynajmu pojazdówPoćwicz samodzielnie: Kompilator PHP online