ITHACK
~ みんなのIT部門 ~
【PHP】トレイト(trait) – クラスコードの再利用

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

PHPにはトレイト(trait)と呼ばれる仕組みがあります。
トレイトはクラスでコードを再利用するために使います。

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

  • トレイト

トレイトとは

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

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

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

基本構文

トレイトは定義と利用の基本構文があります。

定義

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

基本的にはクラスの構文と同じですが、classの部分をtraitとします。
また、クラス変数やクラスメソッド、フィールド、メソッドを定義することができますが、クラス変数は定義できません。

利用

class クラス名 {

    use トレイト名;

}

クラス内でuseキーワードに続いてトレイト名を記述します。
もし、複数のトレイトがある場合は、カンマ(,)区切りで記述することができます。

サンプルコード

トレイトを使ったサンプルコードをご覧ください。

<?php

trait Communication {
    
    private $text;
    
    public function greeting() {
        echo $this->text."\n";
    }
    
}

class Person {
    
    use Communication;
    
    public $name;
    
    public function __construct($name, $text) {
        $this->name = $name;
        $this->text = $text;
    }
    
    public function profile() {
        echo "私の名前は".$this->name."です。\n";
    }
    
}

$watanabe = new Person('Watanabe You', "こんにちは!");
$watanabe->greeting();
$watanabe->profile();

?>
こんにちは!
私の名前はWatanabe Youです。

このコードの解説は次の表をご覧ください。

行数 概要
3~11 Communicationトレイトを定義。
13~28 Personクラスを定義し、Communicationトレイトを使用するよう宣言。
30~32 Personクラスから2つインスタンスを生成し、それぞれでgreetingメソッドとprofileメソッドを呼び出し。

PersonクラスでCommunicationトレイトを利用しているため、インスタンスからgreetingメソッドが使えており、コンストラクタで$textへのアクセスができています。

また、トレイトを利用することはトレイトの定義がクラスで定義されていることに等しいため、$textはprivateですが、クラス内の定義とみなされ正常にアクセスできます。

このあたりは継承と違う部分になります。

複数トレイト

1つのクラスに対して複数のトレイトを利用することができます。

上記サンプルコードにCalculationトレイトを追加した次のコードをご覧ください。

<?php

trait Communication {
    
    private $text;
    
    public function greeting() {
        echo $this->text."\n";
    }
    
}

trait Calculation {
    
    public function addition( $x, $y ) {
        $total = $x + $y;
        echo $x." + ".$y." = ".$total."\n";
    }
    
}

class Person {
    
    use Communication, Calculation;
    
    public $name;
    
    public function __construct($name, $text) {
        $this->name = $name;
        $this->text = $text;
    }
    
    public function profile() {
        echo "私の名前は".$this->name."です。\n";
    }
    
}

$watanabe = new Person('Watanabe You', "こんにちは!");
$watanabe->greeting();
$watanabe->profile();
$watanabe->addition(3, 5);

?>
こんにちは!
私の名前はWatanabe Youです。
3 + 5 = 8

24行目のように複数のトレイトを使用する場合はカンマ(,)区切りでトレイトを記述します。

演習問題

問題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    ===
走る
ジャンプ

まとめ

トレイトはクラスのコードを再利用するための仕組みです。
継承とは異なり、クラス自体に定義されたものとみなされるため、privateな定義もクラスから使えるようになります。