Menu
Coddy logo textTech

銀行システム

CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 89/91。

challenge icon

チャレンジ

簡単

口座、取引、および口座間の送金を処理する銀行システムを構築しましょう。財務データを保護するための適切なカプセル化、異なる口座タイプのための継承、およびデータの整合性を確保するためのバリデーションを備えたシステムを作成します。

コードは以下の6つのファイルに分けて構成します:

  • Transaction.php — 財務操作を記録するための Transaction クラスを作成します。type (string — "deposit", "withdrawal", または "transfer")、amount (float)、および timestamp (string) にはコンストラクタのプロパティ昇格(constructor promotion)を使用してください。すべてのプロパティは public readonly にする必要があります。"[type]: $[amount]" を返す getDescription(): string メソッドを追加してください(金額は小数点以下2桁にフォーマットします)。
  • BankAccount.php — Transaction ファイルをインクルードします。以下の内容を持つ抽象クラス BankAccount を作成します:
    • accountNumber (string, public readonly) と holderName (string, public readonly) のコンストラクタプロパティ昇格
    • 0.0 で初期化された protected な $balance プロパティ
    • 取引履歴を保存するための private な配列
    • getBalance(): float — 現在の残高を返します
    • deposit(float $amount): string — 残高を加算し、取引を記録し、"Deposited: $[amount]" を返します
    • abstract withdraw(float $amount): string — 子クラスで引き出しルールを実装します
    • addTransaction(Transaction $t): void — 履歴に取引を追加するための protected メソッド
    • getTransactionCount(): int — 取引件数を返します
  • SavingsAccount.php — BankAccount ファイルをインクルードします。BankAccount を継承した SavingsAccount クラスを作成します:
    • クラス定数 INTEREST_RATE を 0.02 (2%) に設定します
    • withdraw(float $amount): string — 金額が残高を超える場合は "Insufficient funds" を返し、そうでない場合は差し引き、取引を記録し、"Withdrew: $[amount]" を返します
    • applyInterest(): string — 現在の残高に対する利息を計算し、預金として追加し、"Interest applied: $[interest]" を返します
  • CheckingAccount.php — BankAccount ファイルをインクルードします。BankAccount を継承した CheckingAccount クラスを作成します:
    • コンストラクタ経由で設定される private な $overdraftLimit プロパティ(デフォルト値 100.0 の第3引数を追加します)
    • withdraw(float $amount): string — 金額が「残高 + 当座貸越限度額」を超えない場合に引き出しを許可します。失敗した場合は "Insufficient funds (overdraft limit: $[limit])" を、成功した場合は "Withdrew: $[amount]" を返します
    • getOverdraftLimit(): float — 当座貸越限度額を返します
  • Bank.php — 両方の口座ファイルをインクルードします。口座を管理する Bank クラスを作成します:
    • 口座番号をインデックスとした口座を保存する private な配列
    • 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) の2つの入力を受け取ります。

    口座 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桁にフォーマットしてください。

送金はアトミックである必要があることに注意してください。つまり、引き出しが失敗した場合、入金は行われません。protected な $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内の各アカウントについて:
//   - typeが "savings" の場合、SavingsAccountを作成
//   - typeが "checking" の場合、CheckingAccountを作成(当座貸越が提供されている場合はそれを含める)
//   - 銀行にアカウントを追加
//   - 初回金額を入金

// TODO: 各操作を処理する
// $operations内の各操作について:
//   - "deposit": deposit() の結果を出力
//   - "withdraw": withdraw() の結果を出力
//   - "transfer": transfer() の結果を出力
//   - "interest": applyInterest() の結果を出力(普通預金のみ)
//   - "balance": "[holder] balance: $[balance]" を出力(小数点以下2桁)

?>

オブジェクト指向プログラミングのすべてのレッスン