@ PHP

OOP:継承

継承とは、あるクラスのメソッドやプロパティを引き継いで新しいクラスを定義することです。

継承されたクラスをスーパークラス(親クラスまたは規定クラス)、継承したクラスをサブクラス(子クラスまたは派生クラス)と呼びます。

PHP では多重継承は許されておらず、継承することのできるクラスは1つです。

書式は、クラス名に続けて extends キーワードと継承するクラス名を指定します。

Employee クラスを継承した Job クラスを定義してみます。

root
 ├── Person.php // Person クラス
 ├── Employee.php // Employee スーパークラス
 ├── Job.php // Job サブクラス
 └── extends.php // 実行ファイル

Job.php

<?php
require_once ('Employee.php');

class Job extends Employee
{

}

スーパークラス Employee に業務内容を表示する work() メソッドを追加してみます。

Employee.php

<?php

class Employee
{

    const PARTTIME = 0x01;

    const REGULAR = 0x02;

    const CONTRACT = 0x03;

    private static $company = 'インターネーション';

    public static function getCompany()
    {
        return self::$company;
    }

    public function work()
    {
        print '業務内容:書類整理';
    }

}

Person.php

<?php

class Person
{

    public $firstName;

    public $lastName;

    public function __construct(string $firstName, string $lastName)
    {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }

    public function show()
    {
        print "氏名:{$this->lastName}{$this->firstName}";
    }

}

extends.php

<?php
require_once('Person.php');
require_once('Job.php');

$p = new Person('太郎', '山田');
$j = new Job();

$p->show();

print '<hr>';
print '社名:'.Employee::getCompany();
print '<br>';
print '雇用形態:'.Employee::REGULAR;
print '<br>';

$j->work();

オーバーライド

スーパークラスに定義されたプロパティやメソッドをサブクラスで同じ名前で定義すると、サブクラスではそのプロパティやメソッドの実装が上書きされます。これをオーバーライドと言います。

Employee クラスに新たに追加した work() メソッドを Job クラスでオーバーライドしてみます。

root
 ├── Person.php // Person クラス
 ├── Employee.php // Employee スーパークラス
 ├── Job.php // Job サブクラス
 └── override.php // 実行ファイル

Job.php

<?php
require_once ('Employee.php');

class Job extends Employee
{

    public function work()
    {
        print '業務内容:PHPプログラム';
    }

}

Employee.php

<?php

class Employee
{

    const PARTTIME = 0x01;

    const REGULAR = 0x02;

    const CONTRACT = 0x03;

    private static $company ='インターネーション';

    public static function getCompany()
    {
        return self::$company;
    }

    public function work()
    {
        print '業務内容:書類整理';
    }

}

Person.php

<?php

class Person
{

    public $firstName;

    public $lastName;

    public function __construct(string $firstName, string $lastName)
    {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }

    public function show()
    {
        print "氏名:{$this->lastName}{$this->firstName}";
    }

}

override.php

<?php
require_once('Person.php');
require_once('Job.php');

$p = new Person('太郎', '山田');
$j = new Job();

$p->show();

print '<hr>';
print '会社名:'.Employee::getCompany();
print '<br>';
print '雇用形態:'.Employee::REGULAR;
print '<br>';

$j->work();

Employee クラスでは業務内容を表す work() メソッドは「業務内容:書類整理」と出力しますが、Job クラスでは「業務内容:PHP プログラム」と出力されるよう work() メソッドをオーバーライドしました。

スーパークラスのメソッドの呼び出し

スーパークラスの機能を継承しつつ、サブクラス独自の機能を追加する場合もあります。

このような場合は、サブクラスのメソッドからスーパークラスのメソッドを明示的に呼び出す必要があります。

次のように parent キーワードを使って、サブクラスのメソッドからスーパークラスのメソッドを呼び出すことができます。

Employee クラスを継承して work() メソッドに機能追加をする PrevJob クラスを新たに作ってみます。

root
 ├── Person.php // Person クラス
 ├── Employee.php // Employee スーパークラス
 ├── PrevJob.php // PrevJob サブクラス
 └── parent.php // 実行ファイル

PrevJob.php

<?php
require_once ('Employee.php');

class PrevJob extends Employee
{

    public function work()
    {
        parent::work();
        print '(在宅勤務)';
    }

}

Employee.php

<?php

class Employee
{

    const PARTTIME = 0x01;

    const REGULAR = 0x02;

    const CONTRACT = 0x03;

    private static $company = 'インターネーション';

    public static function getCompany()
    {
        return self::$company;
    }

    public function work()
    {
        print '業務内容:プログラム';
    }

}

Person.php

<?php

class Person
{

    public $firstName;

    public $lastName;

    public function __construct(string $firstName, string $lastName)
    {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }

    public function show()
    {
        print "氏名:{$this->lastName}{$this->firstName}";
    }

}

parent.php

<?php
require_once('Person.php');
require_once('PrevJob.php');

$p = new Person('太郎', '山田');
$j = new PrevJob();

$p->show();

print '<hr>';
print '会社名:'.Employee::getCompany();
print '<br>';
print '雇用形態:'.Employee::REGULAR;
print '<br>';

$j->work();

Employee クラス業務内容を出力する work() メソッドの機能は継承しつつ、新たに「在宅勤務」という内容を追加することができました。

スーパークラスのコンストラクタの呼び出し

スーパークラスのコンストラクタを流用してサブクラスのスーパークラスを定義することもできます。

Person クラスの firstaName lastName プロパティに加えて middleName プロパティを追加した Foreigner クラスを Person クラスのサブクラスとして定義してみます。

root
 ├── Person.php // Person スーパークラス
 ├── Foreigner.php // Foreigner サブクラス
 └── parent-conts.php // 実行ファイル

Foreigner.php

<?php
require_once ('Person.php');

class Foreigner extends Person
{

    public $middleName;

    public function __construct(string $firstName, string $middleName, string $lastName)
    {
        parent::__construct($firstName, $lastName);
        $this->middleName = $middleName;
    }

    public function show()
    {
        print "氏名:{$this->firstName}・{$this->middleName}・{$this->lastName}";
    }
}

コンストラクタのメソッドの一種なので、parent::__construct・・・の書式は変わりません。

Person.php

<?php

class Person
{

    public $firstName;

    public $lastName;

    public function __construct(string $firstName, string $lastName)
    {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }

    public function show()
    {
        print "氏名:{$this->lastName}{$this->firstName}";
    }

}

parent-conts.php

<?php
require_once('Foreigner.php');
require_once('Job.php');

$p = new Foreigner('太郎', 'クリスティアーノ', '山田');
$j = new Job();

$p->show();

print '<hr>';
print '会社名:'.Employee::getCompany();
print '<br>';
print '雇用形態:'.Employee::REGULAR;
print '<br>';

$j->work();

オーバーライドの禁止

final 修飾子を使って、オーバーライドを明示的に禁止できます。

Employee クラスに給料の初期値を格納する $salary プロパティとそれを出力する getSalary()メソッド 定義し、Job クラスの getSalary()メソッドでオーバーライドしてみます。

root
 ├── Person.php // Person スーパークラス
 ├── Foreigner.php // Foreigner サブクラス
 ├── Employee.php // Employee スーパークラス
 ├── Job.php // Job サブクラス
 └── final.php // 実行ファイル

Employee.php

<?php

class Employee
{

    const PARTTIME = 0x01;

    const REGULAR = 0x02;

    const CONTRACT = 0x03;


    private static $company;

    public $salary = 250000;


    public function work()
    {
        print '業務内容:書類整理';
    }

    public static function getCompany()
    {
        return self::$company;
    }

    public static function setCompany($value)
    {
        self::$company = $value;
    }

    public final function getSalary()
    {
        return $this->salary;
    }

}

Employee クラスを継承した Job クラスで getSalary() メソッドをオーバーライドして、給料を 1.5 倍にしてみます。

Job.php

<?php
require_once ('Employee.php');

class Job extends Employee
{

    public function work()
    {
        print '業務内容:PHPプログラム';
    }

    public function getSalary()
    {
        $this->salary = $this->salary * 1.5;
        return $this->salary;
    }

}

Person.php

<?php

class Person
{

    public $firstName;

    public $lastName;

    public function __construct(string $firstName, string $lastName)
    {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }

    public function show()
    {
        print "氏名:{$this->lastName}{$this->firstName}";
    }

}

Foreigner.php

<?php
require_once ('Person.php');

class Foreigner extends Person
{

    public $middleName;

    public function __construct(string $firstName, string $middleName, string $lastName)
    {
        parent::__construct($firstName, $lastName);
        $this->middleName = $middleName;
    }

    public function show()
    {
        print "氏名:{$this->firstName}・{$this->middleName}・{$this->lastName}";
    }
}

final.php

<?php
require_once('Foreigner.php');
require_once('Job.php');

$p = new Foreigner('太郎', 'クリスティアーノ', '山田');

$j = new Job();

$p->show();

$j->setCompany('インターネーション');

print '<hr>';
print '会社名:'.Employee::getCompany();
print '<br>';
print '雇用形態:'.Employee::REGULAR;
print '<br>';

$j->work();

print '<br>';

$j->getSalary();
print '給料:'.$j->salary;

Employee クラスの getSalary()メソッドは final キーワードをつけて宣言しているので、Cannot override final method Employee::getSalary とエラーが表示され、オーバーライドできなくなっています。

PHP: オブジェクトの継承 – Manual