【PHP】Lesson5-5:クラスの継承を理解しよう

ながみえ

一つ前のレッスンでは 静的メンバとインスタンスメンバ について学習しました。

今回は クラスの継承 について見ていきましょう。

Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:関数編
Lesson4:データ構造編
Lesson5:クラス

 ・Lesson5-1:クラスを定義しよう
 ・Lesson5-2:コンストラクタを理解しよう
 ・Lesson5-3:アクセス修飾子とカプセル化を理解しよう
 ・Lesson5-4:クラスメンバを理解しよう
 ・Lesson5-5:クラスの継承を理解しよう ◁今回はココ
 ・Lesson5-6:メソッドのオーバーライドを理解しよう
 ・Lesson5-7:抽象クラスを理解しよう
 ・Lesson5-8:インターフェースを理解しよう
 ・Lesson5-9:トレイトを理解しよう
 ・確認問題5-1:モンスター捕獲ゲームを作ろう
 ・確認問題5-2:マインスイーパを作ろう

<<前のページ

学習記事一覧

次のページ>>

クラスの継承の基本と使い方をマスターしよう

PHPのオブジェクト指向において「クラスの継承」は、コードの再利用性や拡張性を高めるために欠かせない重要な機能です。

本記事では、親クラス・子クラスの基本的な仕組みや、実際にどのように継承を活用できるのかをわかりやすく解説します。

「extendsの使い方が知りたい」「親クラスと子クラスの違いがよく分からない」と感じている方にもピッタリの内容です。

ぜひこの記事で、継承の基礎から活用方法まで一緒に身につけていきましょう!

クラス継承とは何か?|基本構文とコード例

クラスの継承 とは、既存のクラス(親クラス)の機能やプロパティを新しいクラス(子クラス)が受け継ぐ仕組みです。

子クラスは親クラスの機能を使ったり、追加や上書き(オーバーライド)したりできます。

PHPにおける継承は extendsキーワード を用いて以下のように書きます。

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 "わんわん!" . PHP_EOL;
    }
}
class Cat extends Animal {			// Animalクラスを継承したCatクラスの定義
    public function bark() {		// Catクラスの独自メソッド
        echo "にゃーにゃー!" . PHP_EOL;
    }
}

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

このように継承を利用することで、共通する機能を親クラスにまとめ、コードの再利用性と拡張性を向上させることができます。

アクセス修飾子と継承の関係|public・protected・privateの違い

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

  • public(パブリック):クラスの外部や内部からアクセス可能。
  • protected(プロテクテッド):クラス自身とその子クラスからのみアクセス可能。
  • private(プライベート):クラス自身からのみアクセス可能。

これらのアクセス修飾子と継承を組み合わせたコードの例を見てみましょう。

class ParentC {								// ParentCクラス(親クラス)の定義
    public $publicProp = "Public";			// 外部からアクセス可能
    protected $protectedProp = "Protected";	// 子クラスからもアクセス可能
    private $privateProp = "Private";		// 自クラス内からのみアクセス可能

    public function showProps() {			// 継承させたいメソッド
        echo $this->protectedProp . PHP_EOL;
        echo $this->privateProp . PHP_EOL;
    }
}

class ChildC extends ParentC {					// ParentCクラスを継承するChildCクラスの定義
    public function showProtected() {			// このクラスの独自メソッド
        echo $this->protectedProp . PHP_EOL;	// 親クラスのプロパティにアクセス:OK
        echo $this->privateProp;				// エラー発生:private変数にはアクセスできない
    }
}

$child = new ChildC();		// インスタンス生成
$child->showProtected();	// 独自メソッドの呼び出し

このように、継承先のクラスではprotected プロパティやメソッドにアクセスできますが、private はアクセスできません。

セキュリティや安全性を考慮して、適切なアクセス修飾子を設定することが重要です。

まとめ|継承の理解で広がるPHPプログラミング

クラスの継承について学んだことで、親クラスから子クラスへの機能の受け継ぎ方や、アクセス修飾子によるメンバの公開範囲の違いが理解できるようになりました。

これにより、共通部分を親クラスにまとめて、効率的にコードを再利用できるようになり、より柔軟で拡張性のあるプログラム設計が可能になります。

この知識は、実践的なPHP開発や大規模なアプリケーションの設計でも非常に役立つスキルです。

次回以降のレッスンでも、さらに深いオブジェクト指向のテクニックに挑戦し、着実にステップアップしていきましょう!

演習問題|継承を活用して動物の行動を表現しよう

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

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

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

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

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

この演習の要件

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

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

ただし、以下のような実行結果となること。

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

解き方のヒント

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

Q
ヒント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メソッドを呼び出す。

Q
ヒント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();    // 子クラスの独自メソッドを使用

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

演習問題の答え合わせ

この問題の正解コードとその解説は以下の通りです。

クリックして開いて確認してください。

Q
正解コード
<?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();    // 子クラスの独自メソッドを使用
Q
正解コードの解説

コードをブロックごとに分割して解説します。

親クラスの定義

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学習サイトにするため、ぜひ 問い合わせフォーム からご意見下さい。

<<前のページ

学習記事一覧

次のページ>>

記事URLをコピーしました