PHPにおける継承とextends、オーバーライドとparent、final、protectedWeb業界で働くためのPHP入門(17)(1/3 ページ)

オープンソースのWeb開発向けスクリプト言語「PHP」の文法を一から学ぶための入門連載。今回は、クラスを拡張する方法として、継承を扱います。

» 2018年05月10日 05時00分 公開

 オープンソースのWeb開発向けスクリプト言語「PHP」の文法を一から学ぶための入門連載「Web業界で働くためのPHP入門」。今回はクラスを拡張する方法として、継承を扱います。

「継承」とは

 継承とは、あるクラスのメンバを引き継ぐことでクラスを拡張する方法です。具体的にはどういうことかについて、簡単なサンプルを交えながら確認しましょう。

継承では「extends」と記述する

 継承を行うには、まず、基本となるクラスが必要です。それを作成します。以下のAnimalクラスを作成してください。

<?php
class Animal
{
    //名前のプロパティ
    private $name = "";
    
    //名前のゲッタ
    public function getName(): string
    {
        return $this->name;
    }
    //名前のセッタ
    public function setName(string $name): void
    {
        $this->name = $name;
    }
}
リスト1 phplesson/chap17/Animal.php

 ソースコードとしては難しいものはありません。名前を表すプロパティとそのアクセサメソッドのみです。

 さらに、もう1つクラスを作成します。以下のDogクラスを作成してください。

<?php
class Dog extends Animal  // (1)
{
    //鳴き声を得るメソッド
    public function call(): string
    {
        return "わんわん";
    }
}
リスト2 phplesson/chap17/Dog.php

 鳴き声を表す文字列をリターンするメソッドが1つのみのクラスです。

このリスト2には見慣れない記述があります。それが(1)の「extends」です。この(1)の記述が継承を表します。

 通常のクラス宣言、つまり「class クラス名」に続けて「extends クラス名」を記述します。すると、ここで宣言するクラスはextendsの後に記述されたクラスを継承したことになります。リスト2の(1)では「DogクラスはAnimalクラスを継承した」ということになります。

 そして、このextendsの右に記述したクラスのことを「親クラス」といい、左に記述したクラスを「子クラス」といいます。リスト2の(1)ではAnimalが親クラス、Dogが子クラスとなります。構文としては以下のようになります。

構文 継承

class 子クラス extends 親クラス {……}


継承すると親のメンバを全て引き継ぐ

 ここまで説明した内容はあくまで継承の書式です。次に「継承することでどういったメリットがあるのか」「どのようにクラスが拡張されているのか」について見ていきます。これは、これらのクラスを利用してみると分かります。

 そのためのphpファイルを作成しましょう。以下のcallDog.phpを作成し、実行してください。

<?php
require_once("Animal.php");
require_once("Dog.php");
 
$pet = new Dog();  // (1)
$pet->setName("ぽち");  // (2)
print($pet->getName()."の鳴き声は".$pet->call());  // (3)
リスト3 phplesson/chap17/callDog.php

 実行結果は以下の通りです。

ぽちの鳴き声はわんわん

 リスト3で注目するのは、(2)と(3)の前半です。(1)でDogクラスをnewしています。リスト2を見れば分かるように、Dogクラスにはcall()メソッドしか記述されていません。そのため、(3)の後半、「$pet->call()」は理解できます。

 一方、(2)のsetName()メソッドや(3)の前半のgetName()メソッドの実行はどういった仕組みなのでしょうか。リスト2のDogクラスに記述されていないメソッドを利用しているにもかかわらず、エラーとなりません。

 これが、継承の仕組みです。継承関係がある場合、子クラスは親クラスのメンバを全て引き継ぎます。例えば、リスト2だと子クラスであるDogクラスは、Animalクラスのメンバを引き継ぎます。たとえ、Dogクラス内には何の記述がなくても、Animalのメンバがそのまま含まれることになります(図1)。

図1 子クラスには親クラスのメンバがそのまま含まれる

 リスト3の(2)や(3)で呼び出しているsetName()メソッドやgetName()メソッドは、Dogクラスの中に含まれるAnimalクラス部分のメソッドを呼び出しているのです。

コラム「多重継承」

 PHPの継承では、親クラスとして指定できるのは1つだけであり、親クラスを複数指定できません。ところが、言語によっては複数指定できるものもあり、このような継承の仕方を「多重継承」といいます。


親クラスファイルも読み込んでおく

 ここで、リスト3の「require_once」部分に注目してください。リスト3ではDogクラスしか利用していません。となると、Animal.phpの読み込みは不要ではないかと考えるかもしれません。しかし、この2行目を削除して実行すると以下のエラーとなります。

Fatal error: Class 'Animal' not found in C:\xampp\htdocs\phplesson\chap17\Dog.php on line 2

 Dogクラス内で利用しているAnimalクラスが見つからないというエラーメッセージです。このように、実行部分で直接利用していないクラスでも、親クラスとして指定している場合は、そのクラスが記述されたファイルをrequire_onceで読み込んでおく必要があります。

 さらに、順番にも注意してください。親クラスを先に読み込んでおくようにしてください。

コラム「継承関係はis-a関係」

 上で紹介したDogクラスと同じようにAnimalクラスを継承したCatクラスというのを考えます。DogもCatも同じ親を持つクラスなので、クラスの核となる部分は同じです。このように、核となる部分が同じで、その差分のみを独自のクラスとしたい場合に継承は非常に便利な仕組みです。

 ところで、核となる部分が同じならば、広い意味ではDogとCatはAnimalクラスの一種と考えることもできます。このような関係を「is-a」関係といいます。これは、

Dogクラスは(is)Animalクラスの一種(a)

という英語表現が由来です。


       1|2|3 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。