抽象クラス (abstract)
テクノロジ系 / class-advanced (継承 / オーバーライド / abstract / interface / static / const / final)
抽象クラス (abstract)
Lesson 7 / Chapter 4
ゴール
abstract class PaymentMethod {
abstract public function charge(int $amount): bool;
}abstract classを そのままは new できない ことが分かる- 子クラスに
charge()の実装を強制できる - 「枠は親、具体は子」という設計が書ける
抽象クラスとは
共通の枠だけは親で決める。 中身は子クラスで必ず書きなさい。
- 抽象クラス = そのままではインスタンス化できないクラス
- 必ず継承して、抽象メソッドを実装した子クラスを経由して使う
- 「決済を実行できる支払い手段」など 抽象的な概念だけ を親に置く
書き方
<?php
abstract class PaymentMethod {
abstract public function charge(int $amount): bool;
}abstract classでクラス自体を抽象にabstract functionで中身を書かないメソッド宣言- 本体
{ ... }を持たず、;で終わる
new できない
<?php $p = new PaymentMethod(); // ❌ Fatal error: Cannot instantiate abstract class PaymentMethod
- 抽象クラスは直接
newできない - 「決済できる支払い手段」は具体形 (Card / BankTransfer) があってこそ意味を持つ
- 必ず子クラスを作って使う
子クラスで実装する
<?php
class Card extends PaymentMethod {
public function __construct(private string $cardNumber) {}
public function charge(int $amount): bool {
// 実務では決済 SDK を呼ぶ。ここでは成功したことにする
echo "カード {$this->cardNumber} で {$amount} 円決済\n";
return true;
}
}
$c = new Card('4242-4242-4242-4242');
$c->charge(1500); // カード 4242-... で 1500 円決済- 子クラスは 抽象メソッドを必ず実装
- 実装し忘れると「子クラスもまだ抽象だ」とエラーになる
- 本番ではカード番号を直接持たず、決済 SDK のトークンを使う
別の子クラスも同じ枠で書ける
<?php
class BankTransfer extends PaymentMethod {
public function charge(int $amount): bool {
echo "銀行振込で {$amount} 円請求\n";
return true;
}
}
function pay(PaymentMethod $m, int $amount): void {
$m->charge($amount);
}
pay(new Card('4242-...'), 1500);
pay(new BankTransfer(), 1500);CardもBankTransferも 同じcharge()で呼べる- 新しい支払い手段を増やしても
pay()の中身は変えなくていい
abstract と interface
| abstract class | interface |
|---|---|
| 共通実装も親に書ける | 契約 (宣言) だけ |
| 1 つだけ継承 | 複数 implement できる |
| 共通の枠 + 共通実装が欲しい | メソッドの型だけ揃えたい |
- 共通実装が欲しい →
abstract - 契約だけ →
interface(次章 ch05)
このチャプターでできるようになること
✅ abstract class がインスタンス化できないことが分かる
✅ abstract function で子に実装を強制できる
✅ 「枠は親が決めて、具体は子で書く」設計を組める
✅ 抽象クラスとインターフェースの使い分けが言える
→ ドリルへ
考えてみよう
既定では正解・不正解の判定はしません。自分のペースで「答えを見る」を。採点してほしい場合だけ「採点してほしい」を押してください。
ドリル 01 — abstract PaymentMethod を継承した Card
題材
EC サイトの決済処理。複数の支払い手段を共通の枠で扱うため、親で charge() の存在だけ強制し、具体の処理は子に書かせる。
> 本番では Stripe / PAY.JP の SDK を呼ぶが、ここでは練習のため文字列で返す。
やること
abstract class PaymentMethod を定義してください。
abstract public function charge(int $amount): string;を宣言する (中身は書かない)
PaymentMethod を継承した Card クラスを定義してください。
charge(int $amount): stringを実装して"カードで {amount} 円を決済しました"を返す
Card をインスタンス化し、charge(1500) の結果を 1 行出力してください。
期待される出力
カードで 1500 円を決済しました
ヒント
abstract class PaymentMethod { abstract public function charge(int $amount): string; }class Card extends PaymentMethod { ... }echo $c->charge(1500) . "\n";- 文字列連結は
"カードで {$amount} 円を決済しました"でも. ' '.でも OK
採点
php scripts/grade.php topics/class-advanced/ch04-abstract/drill/01-abstract-payment/