ch04 8章中 4章目

ch04 — 抽象クラス (abstract)

スライドで見る

この章を AI と学ぶ

💬 AI に聞く質問例 3 件
  1. 「ch04 — 抽象クラス (abstract)」のつまずきやすいポイントを、初学者向けに3つ教えてください

    ChatGPT Claude Gemini

  2. 「ch04 — 抽象クラス (abstract)」について、自分の手で試せる練習問題を3つ出してください (難易度を上げながら)

    ChatGPT Claude Gemini

  3. 「ch04 — 抽象クラス (abstract)」を学んだ後、次に学ぶと良いトピックは何ですか?理由も教えてください

    ChatGPT Claude Gemini

なぜ 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 を継承した Cardcharge() を実装する

解説スライド 全 9 枚

右の ボタン キー(またはスワイプ)で次のスライドに進めます。 下の「縦表示」を開くと全スライドを一気に読めます。

  1. 抽象クラス (abstract)

    Lesson 7 / Chapter 4

  2. ゴール

    abstract class PaymentMethod {
        abstract public function charge(int $amount): bool;
    }
    • abstract classそのままは new できない ことが分かる
    • 子クラスに charge() の実装を強制できる
    • 「枠は親、具体は子」という設計が書ける
  3. 抽象クラスとは

    共通の枠だけは親で決める。
    中身は子クラスで必ず書きなさい。
    • 抽象クラス = そのままではインスタンス化できないクラス
    • 必ず継承して、抽象メソッドを実装した子クラスを経由して使う
    • 「決済を実行できる支払い手段」など 抽象的な概念だけ を親に置く
  4. 書き方

    <?php
    abstract class PaymentMethod {
        abstract public function charge(int $amount): bool;
    }
    • abstract class でクラス自体を抽象に
    • abstract function で中身を書かないメソッド宣言
    • 本体 { ... } を持たず、 ; で終わる
  5. new できない

    <?php
    $p = new PaymentMethod();
    // ❌ Fatal error: Cannot instantiate abstract class PaymentMethod
    • 抽象クラスは直接 new できない
    • 「決済できる支払い手段」は具体形 (Card / BankTransfer) があってこそ意味を持つ
    • 必ず子クラスを作って使う
  6. 子クラスで実装する

    <?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 のトークンを使う
  7. 別の子クラスも同じ枠で書ける

    <?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);
    • CardBankTransfer同じ charge() で呼べる
    • 新しい支払い手段を増やしても pay() の中身は変えなくていい
  8. abstract と interface

    abstract class interface
    共通実装も親に書ける 契約 (宣言) だけ
    1 つだけ継承 複数 implement できる
    共通の枠 + 共通実装が欲しい メソッドの型だけ揃えたい
    • 共通実装が欲しい → abstract
    • 契約だけ → interface (次章 ch05)
  9. このチャプターでできるようになること

    abstract class がインスタンス化できないことが分かる ✅ abstract function で子に実装を強制できる ✅ 「枠は親が決めて、具体は子で書く」設計を組める ✅ 抽象クラスとインターフェースの使い分けが言える

    → ドリルへ

1 / 9
📜 スライドを全部一気に読む(縦表示)

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);
  • CardBankTransfer同じ charge() で呼べる
  • 新しい支払い手段を増やしても pay() の中身は変えなくていい

abstract と interface

abstract class interface
共通実装も親に書ける 契約 (宣言) だけ
1 つだけ継承 複数 implement できる
共通の枠 + 共通実装が欲しい メソッドの型だけ揃えたい
  • 共通実装が欲しい → abstract
  • 契約だけ → interface (次章 ch05)

このチャプターでできるようになること

abstract class がインスタンス化できないことが分かる ✅ abstract function で子に実装を強制できる ✅ 「枠は親が決めて、具体は子で書く」設計を組める ✅ 抽象クラスとインターフェースの使い分けが言える

→ ドリルへ

この章で取り組む 演習問題の流れ (1ステップ)
  1. 01 ドリル 01 — abstract PaymentMethod を継承した Card README.md starter.php answer.php

演習問題の詳細

この章の演習問題の内容を読めます。実際に手元で解くには教材リポジトリを clone してください。

ドリル 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 ランタイム読込で数秒かかります。

PHP ランタイム未読込

          

        

演習問題(1問)

  1. ドリル 01 — abstract PaymentMethod を継承した Card

    README.md starter.php answer.php

サイト内で問題文・雛形・解答例を確認できます。実際に手元で解くには教材リポジトリを clone してください。

完了にすると進捗に反映されます