【PHP】トレイト(trait) - クラスコードの再利用

【PHP】トレイト(trait) - クラスコードの再利用

PHPにはトレイトと呼ぶ仕組みがあります。

トレイトはクラスのコードを再利用するために使用します。

ここでは、トレイトについて解説します。

検証環境

トレイト

トレイトは“クラスのコードを再利用する仕組み”です。

フィールドやメソッドを定義し、トレイトを利用宣言したクラスはそれらを使うことができます。

継承と似ていますが、トレイトは“コードの再利用”を目的としており、オブジェクトを表現するものではありません。

トレイトの定義

トレイトを使うには定義が必要です。

基本構文

trait トレイト名 {
    // クラス変数・クラスメソッド
    // フィールド・メソッド etc...
}

基本的にはクラスの構文と同じですが、classの部分をtraitにします。

また、クラスとは異なり、クラス変数は定義できません。

サンプル

// コミュニケーショントレイト
trait Communication {
    
    // メッセージ
    private $message;
    
    // あいさつ
    public function greeting() {
        echo $this->message . "\n";
    }
    
}
$ php sample.php
$

4〜11行目がCommunicationトレイトの定義です。

このトレイトは$messageフィールドとgreetingメソッドを持ちます。

トレイトの利用

トレイトを利用するにはクラスで利用することを宣言します。

利用するクラスはトレイトのprivateなプロパティ(フィールドやメソッド等)でも、クラスの定義とみなされるため、正常にアクセスできます。

基本構文

class クラス名 {
    
    ___ih_hl_start
    use トレイト名1, トレイト名2, ...;
    ___ih_hl_end

}

クラス内でuseキーワードに続いてトレイト名を記述します。

複数トレイトを利用する場合は、カンマ(,)区切りで指定できます。

サンプル

<?php
 
// コミュニケーショントレイト
trait Communication {
    
    // メッセージ
    private $message;
    
    // あいさつ
    public function greeting() {
        echo $this->message . "\n";
    }
    
}

// 人間クラス
class Person {
    
    // 利用トレイト
    ___ih_hl_start
    use Communication;
    ___ih_hl_end
    
    // 名前
    public $name;
    
    // コンストラクタ
    public function __construct( $name, $message ) {
        $this->name = $name;
        ___ih_hl_start
        $this->message = $message;
        ___ih_hl_end
    }
    
    // 自己紹介
    public function introduction() {
        ___ih_hl_start
        $this->greeting();
        ___ih_hl_end
        echo "My name is " . $this->name . ".\n";
    }
    
}

$person = new Person('TANAKA', 'Hello.');

$person->introduction();
 
?>
$ php sample.php
Hello.
My name is TANAKA.

20行目でCommunicationトレイトをPersonクラスで利用することを宣言しています。

そのため、28行目や33行目のように$messageフィールドやgreetingメソッドを使うことが可能です。

また、アクセス修飾子がprivateなプロパティへのアクセスも、問題なく処理されたことが分かります。

トレイトの組み合わせ

トレイトで他のトレイトを利用することができます。

利用するにはクラスと同様にuseキーワードを使用します。

<?php
 
// コミュニケーショントレイト
trait Communication {
    
    // メッセージ
    private $message;
    
    // あいさつ
    public function greeting() {
        echo $this->message . "\n";
    }
    
}

// 基本行動
trait BaseAction {
    
    // 利用トレイト
    ___ih_hl_start
    use Communication;
    ___ih_hl_end
    
    // 食事
    public function meal() {
        echo "Eating...\n";
    }
    
}

// 人間クラス
class Person {
    
    // 利用トレイト
    use BaseAction;
    
    // 名前
    public $name;
    
    // コンストラクタ
    public function __construct( $name, $message ) {
        $this->name = $name;
        $this->message = $message;
    }
    
    // 自己紹介
    public function introduction() {
        $this->greeting();
        echo "My name is " . $this->name . ".\n";
    }
    
}

$person = new Person('TANAKA', 'Hello.');

$person->introduction();
$person->meal();
 
?>
こんにちは!
Hello.
My name is TANAKA.
Eating...

20行目でBaseActionトレイトがCommunicationトレイトを使うように宣言しています。

PersonクラスはBaseActionトレイトを利用しており、各トレイトのプロパティに問題なくアクセスできます。

演習問題

問題1

次の実行結果になるプログラムを作成してください。
なお、下記条件を満たすものとします。

  • 次の表のクラス・トレイトを作成する
  • 人間クラス、コンピュータークラスのインスタンスからaddメソッドを実行する
種類 名称 英記 トレイト メソッド
トレイト 計算トレイト Calculation add( $x, $y )
→ 2値の足し算を出力する
具象クラス 人間クラス Person Calculation
具象クラス コンピュータークラス Computer Calculation
=== Person   ===
123 + 456 = 579
=== Computer ===
12345 + 67890 = 80235

問題2

次の実行結果になるプログラムを作成してください。
なお、下記条件を満たすものとします。

  • 次の表のクラス・トレイトを作成する
  • 人間クラスのインスタンスからトレイトで定義したメソッドを全て呼び出す
  • 猫クラスのインスタンスからトレイトで定義したメソッドを全て呼び出す
種類 名称 英記 継承 トレイト フィールド メソッド
トレイト コミュニケーショントレイト Communication greeting()
→ 『こんにちは』を出力する。
introduction()
→ 『私の名前は●●です』を出力する
※ 『●●』は$nameフィールドの値
トレイト 運動トレイト Motion run()
→ 『走る』を出力する
jump()
→ 『ジャンプ』を出力する
抽象クラス 生物クラス Creature $name ・コンストラクタ
→ $nameの値を初期化
具象クラス 人間クラス Person Creature Communication
Motion
具象クラス 猫クラス Cat Creature Motion
=== Person ===
こんにちは
私の名前はWatanabe Youです。
走る
ジャンプ
=== Cat    ===
走る
ジャンプ