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

» 2018年05月10日 05時00分 公開
前のページへ 1|2|3       

継承で威力を発揮するアクセス修飾子protected

 継承の最後に、新しいアクセス修飾子を紹介します。アクセス修飾子は連載第14回でpublicとprivateがあることを紹介しました。実は、もう1つ「protected」というのがあります。

privateメンバは子クラスからアクセスできない

 早速、「protectedが、どのような働きをするのか」についてサンプルを作りながら見ていきましょう。ここでは、連載第15回のリスト3のCircleクラスを使います。

 まず、phplesson/chap15/Circle.phpをファイルごとchap17フォルダ内にコピーしてください。次に、このCircleクラスを継承した以下のSphereクラスを作成してください。

<?php
class Sphere extends Circle
{
    //球の表面積を計算するメソッド
    public function getSurfaceArea(): float
    {
        return 4 * self::PI * $this->radius * $this->radius;  // (1)
    }
}
リスト9 phplesson/chap17/Sphere.php

 コメントにあるように、プロパティの半径と定数の円周率を使って球の表面積を計算するメソッドが1つだけです。このSphereクラスを利用する以下のuseSphere.phpを作成し、実行してください。

<?php
require_once("Circle.php");
require_once("Sphere.php");
 
$sphere = new Sphere(5);  // (1)
$surface = $sphere->getSurfaceArea();
print("球の表面積: ".$surface);
リスト10 phplesson/chap17/useSphere.php

 実行結果は、以下のようにエラーとなります。

Notice: Undefined property: Sphere::$radius in C:\xampp\htdocs\phplesson\chap17\Sphere.php on line 7
Notice: Undefined property: Sphere::$radius in C:\xampp\htdocs\phplesson\chap17\Sphere.php on line 7
球の表面積: 0

 エラーの原因は、エラーメッセージにもあるようにリスト9の(1)で存在しない$radiusプロパティにアクセスしていることです。確かに、$radiusプロパティは親クラスであるCircleクラスには記述されていますが、privateプロパティとなっています。privateプロパティは自クラス内でのみアクセス可能なので、子クラスからはアクセスできません(図3)。privateのこの性質はメソッドに対しても当てはまります。

図3 privateプロパティは子クラスからアクセスできない

自クラスと子クラスのみでアクセス可能なprotected

 この問題を解決するために、$radiusプロパティをpublicにするという考え方もありますが、それではカプセル化が実現できません。そこで新しいアクセス修飾子である「protected」を導入します。

 Circleクラスの7行目を下記リスト11のように書き換えて、再度useSphere.phpを実行してください。

<?php
class Circle
{
    //πを表す定数
    const PI = 3.14;
    //半径を表すプロパティ
    protected $radius = 0;
    〜省略〜
}
リスト11 phplesson/chap17/Circle.php

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

球の表面積: 314

 今度はエラーにならずに済みました。

 protectedは自クラスと子クラスからのみアクセス可能なメンバを表します(図4)。

図4 protectedの性質

 一方、publicとは違い、外部のクラスや実行phpからアクセスすることはできません。もしuseSphere.phpに以下のコードを記述し、実行すると、「Fatal error: Uncaught Error: Cannot access protected property Sphere::$radius」と、エラーになります。

$sphere->radius;

 そのため、カプセル化は保たれています。

次回はポリモーフィズム

 次回は、オブジェクト指向の3大特徴の1つであるポリモーフィズムを実現する方法である抽象クラスとインタフェースを扱います。

今回のサンプルコード

 今回のサンプルコードはこちらからダウンロードできます。

前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

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

メールマガジン登録

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