@ PHP

OOP:トレイト

トレイト(trait)とは、再利用可能なソースコード(プロパティやメソッド)をまとめておくための仕組みです。

トレイトの宣言

トレイトを定義するには、class 命令の代わりに trait 命令を使います。

format

trait トレイト名 {
    プロパティの定義;
    メソッドの定義;
}

トレイトとクラスには以下のような違いがあります。

  • trait 自体のインスタンス化は不可能(コンストラクタは可能)。
  • const による定数宣言は不可能(プロパティ、抽象 / 静的 / インスタンスメソッドのみ可能)。
  • クラスを継承したり、インターフェース実装を宣言出来ない。

トレイトの実装

トレイトの機能を利用するには、クラス内部で use 命令を使ってトレイト名を指定します。カンマ区切りで複数のトレイトを組み込むことができます。

format

class クラス名 {
    use トレイト名1, トレイト名2,‥‥;
}

業務内容を設定する「work」プログラムスキルを設定する「skill」2 つのトレイトを組み込んだクラスを定義してみます。

root
├── Person.php // スーパークラス
├── WorkTrait.php // work トレイト
├── SkillTrait.php // skill トレイト
└── StaffInfo.php // 実装クラス

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}";
    }
}

WorkTrait.php

<?php

trait work{

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

SkillTrait.php

<?php

trait skill{

    public function skill($language)
    {
        print "スキル:{$language}";
    }
}

Staffinfo.php

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

class StaffInfo extends Person
{
    use work, skill;

    private $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}";
    }
}

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

$si->show();
print '<hr>';
$si->work('在宅勤務');
print '<br>';
$si->skill('PHP');

アクセサメソッドの実装

値を受け渡しする汎用的なアクセサメソッド機能を持つ共通的なソースコードをトレイトとして切り出すことができます。

root
├── Accessors.php // Accessors トレイト
└── Payment.php // 実装クラス

Accessors.php

<?php

trait Accessors
{

    public function __get($name)
    {
        if ($this->property[$name]) {
            return $this->$name;
        } else {
            throw new Exception("{$name}プロパティは存在しせん。");
        }
    }

    public function __set($name, $value)
    {
        if ($this->property[$name]) {
            $this->$name = $value;
        } else {
            throw new Exception("{$name}プロパティは存在しせん。");
        }
    }
}

Payment.php

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

class Payment
{
    use Accessors;

    private $property = array(
        'price' => 1,
        'amount' => 1
    );

    protected $price = 100;

    private $amount;

    private $tax = 1.15;

    public function getTotal()
    {
        return $this->price * $this->amount * $this->tax;
    }
}

$pay = new Payment();

$pay->price = 20;
$pay->amount = 3;

echo "Total cost: " . $pay->getTotal();

PHP: トレイト – Manual