なぜ abstract が要るか
EC サイトには「カード払い」「銀行振込」「コンビニ払い」と複数の決済手段があるが、どれも 「金額を受け取って結果を返す」 枠は揃えたい。親で枠だけ決めて、具体の処理は子に必ず書かせたい。これが abstract の出番。
abstract の書き方
abstract class でクラス自体を抽象に、abstract function で 中身を書かないメソッド を宣言する。
abstract class PaymentMethod {
abstract public function charge(int $amount): string;
}PaymentMethod は そのままでは new できない。継承して使う。
子に実装を強制する
抽象メソッドを持つクラスを継承した子は、すべての抽象メソッドを実装しないと自分も abstract のまま になる (= new できずエラー)。
class Card extends PaymentMethod {
public function charge(int $amount): string {
return "カードで {$amount} 円を決済しました";
}
}charge() の実装漏れを コードを書いた時点で防げる。
abstract vs interface
| 使い分け | 抽象クラス | インターフェース |
|---|---|---|
| 共通の実装も親に書きたい | ○ | × |
| 契約 (メソッド名) だけ揃えたい | △ | ○ |
| 多重継承的に複数の契約を持たせたい | × | ○ |
共通の処理を親に持たせたいなら abstract、契約だけならインターフェース (次章)。
学習目標
abstract classは インスタンス化できない ことを理解する (new PaymentMethod()は不可)abstract functionは 中身を書かず子で必ず実装 させる仕組み- 「決済手段の共通の枠は親、具体の決済処理は子で必ず書く」を強制できる
ドリル
| no | 内容 |
|---|---|
| 01 | abstract class PaymentMethod を継承した Card で charge() を実装する |
📝 演習: ドリル 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