【PHP】レッスン5-05:クラスの継承を理解しよう

記事内に商品プロモーションを含む場合があります

この記事で学べる知識:クラスの継承

この記事の練習問題を解くために必要な知識:
基礎文法・制御構造・関数・データ構造(レッスン1~4)クラスの定義と使用コンストラクタアクセス修飾子とカプセル化クラスメンバクラスの継承メソッドのオーバーライド抽象クラスインターフェーストレイト

<<前のページ PHP記事一覧 次のページ>>

PHPの「クラスの継承」とは

この章ではPHPにおける「クラスの継承」の意味や使い方を学習します。用語の解説が不要な方はここをクリックして練習問題へ飛びましょう。



オブジェクト指向プログラミングでは、継承は非常に重要な機能です。

継承とは、親クラス(基底クラス)のプロパティやメソッドを子クラス(派生クラス)が引き継ぐ仕組みを指します。

この仕組みにより、既存のコードを再利用しながら新しい機能を追加したり、動作をカスタマイズしたりすることができます。

PHPではextends キーワードを使用してクラスの継承を簡単に実現できます。

【初心者向け】PHPのオブジェクト指向を分かりやすくまとめた概念図。 特にクラスの継承、オーバーライド、抽象クラス、インターフェース、トレイトの関係性を視覚的に理解できるようまとめている。

クラスの継承の基本構文

PHPにおける継承の基本的な書き方は以下のとおりです:

class 親クラス名 {
    // 親クラスのプロパティやメソッド
}

class 子クラス名 extends 親クラス名 {
    // 子クラス独自のプロパティやメソッド
}
  • extends キーワードを使用して、親クラスを継承します。
  • 親クラスのプロパティやメソッドは、そのまま子クラスで利用できます。
  • 子クラスには独自の機能を追加することも可能です。

継承の使用例と解説

class Animal { //Animalクラスの定義
    public function makeSound() { // Animalクラスのメソッド
        echo "Animal sound" . PHP_EOL;
    }
}

class Dog extends Animal {   // Animalクラスを継承したDogクラスの定義
    public function bark() { // Dogクラスのメソッド
        echo "Bark!" . PHP_EOL;
    }
}

$dog = new Dog();  // Dogクラスのインスタンス生成
$dog->makeSound(); // 親クラスのメソッドを呼び出す
$dog->bark();      // 子クラスの独自メソッドを呼び出す
  • クラス Animal は基本的な機能を持つ親クラスです。
  • クラス DogAnimal を継承し、親クラスのメソッド makeSound() をそのまま利用できます。
  • 子クラスでは独自のメソッド bark() を追加し、動作を拡張しています。

このように継承を利用することで、コードの再利用性と拡張性が向上します。

アクセス修飾子と継承における挙動

継承を使用する際は、アクセス修飾子による挙動の違いを理解しておく必要があります。

class ParentClass { // ParentClassクラスの定義
    public $publicProp = "Public";
    protected $protectedProp = "Protected";
    private $privateProp = "Private";

    public function showProps() {
        echo $this->protectedProp . PHP_EOL; // OK
        echo $this->privateProp . PHP_EOL;   // OK
    }
}

class ChildClass extends ParentClass { // ParentClassを継承するChildClassの定義
    public function showProtected() {
        echo $this->protectedProp . PHP_EOL; // OK
        // echo $this->privateProp; // エラー発生
    }
}

$child = new ChildClass();
$child->showProtected();

解説

  1. public:継承先からも外部からもアクセス可能。
  2. protected:継承先からはアクセス可能だが、外部からは不可。
  3. private:親クラス内でのみアクセス可能で、子クラスからはアクセス不可。

ポイント

  • 継承先のクラスでは、protected プロパティやメソッドにアクセスできますが、private はアクセスできません。
  • セキュリティや安全性を考慮して、適切なアクセス修飾子を設定することが重要です。

親クラスのコンストラクタを継承

class Animal {
    protected $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function eat() {
        echo $this->name . " is eating." . PHP_EOL;
    }
}

class Dog extends Animal {
    public function __construct($name) {
        // 親クラスのコンストラクタを呼び出す
        parent::__construct($name);
    }

    public function bark() {
        echo $this->name . " is barking." . PHP_EOL;
    }
}

$dog = new Dog("Buddy");
$dog->eat();   // 親クラスのメソッド
$dog->bark();  // 子クラスの独自メソッド
  • 子クラス Dog は親クラス Animal のコンストラクタをそのまま利用し、名前を初期化しています。
  • parent::__construct($name) を使うことで、親クラスの初期化処理を簡単に再利用できます。
  • 必要に応じて、追加の処理を子クラス側で実装できます。

まとめ

  • クラスの継承はコードの再利用性と拡張性を向上させるための重要な仕組みです。
  • 継承を利用することで親クラスの機能をそのまま使ったり、子クラスに新しい機能を追加したりできます。
  • アクセス修飾子を適切に使い、継承関係における安全性を確保することが大切です。
  • 親クラスのコンストラクタを呼び出すことで、共通の初期化処理を簡潔に記述できます。

クラスの継承の練習問題:犬と猫の動作を継承でシンプルに表現しよう

動物の種類ごとに異なる動作を表現するプログラムを作成しましょう。

この問題ではクラスの継承を使用して、親クラスから共通の機能を受け継ぎながら、子クラスで特有の動作を追加します。

親クラスには動物の名前を保持するプロパティと「鳴く」動作を定義します。

子クラスでは犬と猫を定義し、それぞれ「尻尾を振る」や「ひっかく」といった特有の動作を追加します。

プログラムの最後には、それぞれの動作を出力して動作を確認できるようにしてください。

この問題の要件

以下の要件に従ってコードを完成させてください。

  1. 親クラス「Animal」を作成し、以下を定義すること。
    • protected $name プロパティ:動物の名前を保持する。
    • コンストラクタ:名前を引数で受け取り、プロパティ $name を初期化する。
    • メソッド makeSound():名前と一緒に「鳴いています。」と出力する。
  2. 子クラス「Dog」を作成し、以下を定義すること。
    • Animal クラスを継承すること。
    • メソッド wagTail():名前と一緒に「尻尾を振っています。」と出力する。
  3. 子クラス「Cat」を作成し、以下を定義すること。
    • Animal クラスを継承すること。
    • メソッド scratch():名前と一緒に「ひっかいています。」と出力する。
  4. 動作確認用コードを作成すること。
    • 犬と猫のインスタンスをそれぞれ作成する。
    • 名前は犬が「ポチ」、猫が「タマ」とすること。
    • 各インスタンスの動作を呼び出し、その出力を確認すること。

ただし、以下のような実行結果となるコードを書くこと。

*****↓↓正解コードの実行結果の例↓↓*****

ポチは鳴いています。
ポチは尻尾を振っています。
タマは鳴いています。
タマはひっかいています。

この問題を解くヒント

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

ヒント1【コードの構成を見る】

正解のコードは上から順に以下のような構成となっています。
(※下記の□はコード内のインデントを表しています)

1:<?php – PHPコードの開始宣言。
2:class Animal { – Animalクラスの定義開始。
  □ protected $name; – 名前を保持するプロパティをprotectedで定義。
  □ public function __construct($name) { – コンストラクタの定義開始。
  □ □ $this->name = $name; – 引数$nameをプロパティ$nameに代入。
  □ public function makeSound() { – makeSoundメソッドの定義開始。
  □ □ echo $this->name . "は鳴いています。" . PHP_EOL; – 名前と鳴き声を出力。
3:class Dog extends Animal { – Dogクラスの定義開始(Animalクラスを継承)。
  □ public function wagTail() { – wagTailメソッドの定義開始。
  □ □ echo $this->name . "は尻尾を振っています。" . PHP_EOL; – 名前と尻尾を振る動作を出力。
4:class Cat extends Animal { – Catクラスの定義開始(Animalクラスを継承)。
  □ public function scratch() { – scratchメソッドの定義開始。
  □ □ echo $this->name . "はひっかいています。" . PHP_EOL; – 名前とひっかく動作を出力。
5:$dog = new Dog("ポチ"); – Dogクラスのインスタンスを作成し、名前を「ポチ」に設定。
6:$dog->makeSound(); – Dogクラスで親クラスのmakeSoundメソッドを呼び出す。
7:$dog->wagTail(); – Dogクラスで独自のwagTailメソッドを呼び出す。
8:$cat = new Cat("タマ"); – Catクラスのインスタンスを作成し、名前を「タマ」に設定。
9:$cat->makeSound(); – Catクラスで親クラスのmakeSoundメソッドを呼び出す。
10:$cat->scratch(); – Catクラスで独自のscratchメソッドを呼び出す。

ヒント2【穴埋め問題にする】

以下のコードをコピーし、コメントに従ってコードを完成させて下さい。

<?php
// 動物クラス(親クラス)の定義
class Animal {
    // 名前を保持するプロパティ
    protected $name;

    // コンストラクタ:名前を初期化する
    public function __construct($name) {
        $this->name = $name;
    }

    // 動物が鳴く動作を表示するメソッド
    public function makeSound() {
        echo $this->name . "は鳴いています。" . PHP_EOL;
    }
}

// 犬クラス(子クラス)の定義 - Animalクラスを継承
/*【穴埋め問題1】  
ここでDogクラスを作成し、Animalクラスを継承してください。その中で犬特有の動作を表示するwagTailメソッドを定義し、<名前>は尻尾を振っています。と表示するコードを書いてください。  
*/

// 猫クラス(子クラス)の定義 - Animalクラスを継承
/*【穴埋め問題2】  
ここでCatクラスを作成し、Animalクラスを継承してください。その中で猫特有の動作を表示するscratchメソッドを定義し、<名前>はひっかいています。と表示するコードを書いてください。  
*/

// インスタンス作成と動作確認
// 犬のインスタンスを作成
$dog = new Dog("ポチ");
$dog->makeSound();  // 親クラスのメソッドを使用
$dog->wagTail();    // 子クラスの独自メソッドを使用

// 猫のインスタンスを作成
$cat = new Cat("タマ");
$cat->makeSound();  // 親クラスのメソッドを使用
$cat->scratch();    // 子クラスの独自メソッドを使用

以上がこの問題の穴埋めコードです。

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。



練習問題の解答と解説

この問題の一つの正解例とそのコードの解説を以下に示します。

正解コードの例

例えば以下のようなプログラムが考えられます。

<?php
// 動物クラス(親クラス)の定義
class Animal {
    // 名前を保持するプロパティ
    protected $name;

    // コンストラクタ:名前を初期化する
    public function __construct($name) {
        $this->name = $name;
    }

    // 動物が鳴く動作を表示するメソッド
    public function makeSound() {
        echo $this->name . "は鳴いています。" . PHP_EOL;
    }
}

// 犬クラス(子クラス)の定義 - Animalクラスを継承
class Dog extends Animal {
    // 犬特有の動作を表示するメソッド
    public function wagTail() {
        echo $this->name . "は尻尾を振っています。" . PHP_EOL;
    }
}

// 猫クラス(子クラス)の定義 - Animalクラスを継承
class Cat extends Animal {
    // 猫特有の動作を表示するメソッド
    public function scratch() {
        echo $this->name . "はひっかいています。" . PHP_EOL;
    }
}

// インスタンス作成と動作確認
// 犬のインスタンスを作成
$dog = new Dog("ポチ");
$dog->makeSound();  // 親クラスのメソッドを使用
$dog->wagTail();    // 子クラスの独自メソッドを使用

// 猫のインスタンスを作成
$cat = new Cat("タマ");
$cat->makeSound();  // 親クラスのメソッドを使用
$cat->scratch();    // 子クラスの独自メソッドを使用

正解コードの解説

このコードはクラスの継承を用いて親クラスから機能を引き継ぎ、動物の特性や行動を表現するプログラムです。

コードをブロックごとに分けて詳しく説明します。

親クラスの定義

class Animal {
    protected $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function makeSound() {
        echo $this->name . "は鳴いています。" . PHP_EOL;
    }
}
  1. クラスの定義:
    • class Animal で親クラス Animal を定義します。親クラスは動物の共通機能を持っています。
  2. プロパティの定義:
    • $name は動物の名前を保持するプロパティです。
    • protected はアクセス修飾子で、このクラスとその継承クラス内でのみアクセス可能です。
  3. コンストラクタの定義:
    • __construct() はクラスのインスタンスを作成したときに呼び出される特別な関数です。
    • 引数 $name を受け取り、プロパティ $name を初期化します。
  4. メソッドの定義:
    • makeSound() は動物が鳴く動作を表示するメソッドです。
    • $this->name を使って、プロパティ $name にアクセスしています。

子クラス「Dog」の定義

class Dog extends Animal {
    public function wagTail() {
        echo $this->name . "は尻尾を振っています。" . PHP_EOL;
    }
}
  1. 継承の定義:
    • class Dog extends AnimalAnimal クラスを継承して子クラス Dog を定義します。
    • 継承によりDog は親クラス Animal の機能をそのまま使えます。
  2. 独自メソッドの追加:
    • wagTail() は犬特有の動作を表現するメソッドです。
    • 親クラスのプロパティ $name を利用して、動作メッセージを表示します。

子クラス「Cat」の定義

class Cat extends Animal {
    public function scratch() {
        echo $this->name . "はひっかいています。" . PHP_EOL;
    }
}
  1. 継承の定義:
    • class Cat extends Animal で、Animal クラスを継承して子クラス Cat を定義します。
  2. 独自メソッドの追加:
    • scratch() は猫特有の動作を表現するメソッドです。
    • これにより、親クラスからの機能を利用しつつ、新しい機能を追加できます。

インスタンスの作成とメソッド呼び出し

$dog = new Dog("ポチ");
$dog->makeSound();
$dog->wagTail();

$cat = new Cat("タマ");
$cat->makeSound();
$cat->scratch();
  1. インスタンスの作成:
    • $dog = new Dog("ポチ") で、Dog クラスのインスタンスを作成します。
    • コンストラクタにより、名前「ポチ」が初期化されます。
  2. 親クラスのメソッド呼び出し:
    • $dog->makeSound() は親クラス Animal のメソッドを呼び出して動作します。
  3. 子クラスの独自メソッド呼び出し:
    • $dog->wagTail() は子クラス Dog の独自メソッドを呼び出します。
  4. 複数の子クラスの動作:
    • Cat クラスのインスタンスも同様に作成し、それぞれの動作を確認します。

まとめ

このコードではクラスの継承を用いて親クラスから機能を受け継ぎ、動物の種類ごとに異なる動作を追加する方法を学びました。

  • クラスの継承はコードの再利用性と拡張性を高めるために重要な仕組みです。
  • 親クラスの機能をそのまま使えるだけでなく、子クラスで新しい機能を追加してカスタマイズできます。
  • 継承を理解することで、より効率的で柔軟なプログラムを作成できるようになります。

この解説を参考にして、さらに多様なクラスと継承の応用例に挑戦してみましょう!

<<前のページ PHP記事一覧 次のページ>>

この記事への質問・コメント

この記事を作成するにあたりAIを活用しています。

問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。






    PHPのテキスト&問題集トップへ戻る
    トップページへ戻る