クラスを水平方向に拡張できるPHPの「トレイト」Web業界で働くためのPHP入門(19)(2/3 ページ)

» 2018年06月27日 05時00分 公開

トレイトの利用

 トレイトの作成が一通りできたところで、次にトレイトを利用する方法を解説します。

トレイトの組み込みは「use」

 ここまでに作成したトレイトを各クラスに組み込んでいきましょう。まず、「打つ」を表すHitTraitトレイトを組み込んだTennisPlayerクラスを作成します。

<?php
class TennisPlayer extends SportsPlayer
{
    use HitTrait;  // (1)
 
    //ラケットを表すプロパティ。
    private $racket;
}
リスト4 phplesson/chap19/TennisPlayer.php

 トレイトを組み込んでいるコードが(1)です。トレイトをクラスに組み込むには以下のように記述します。

構文「トレイトの組み込み」

use トレイト名;


 なお、TennisPlayerクラスの他のメンバですが、ここではラケットを表すプロパティのみを記述しています。他に必要なプロパティやメソッドがあれば、ここに追記していきますが、トレイトの解説には不要なので省略しています。

 同様に、「投げる」を表すThrowTraitトレイトを組み込んだHandballPlayerクラスを作成しましょう。

<?php
class HandballPlayer extends SportsPlayer
{
    use ThrowTrait;  // (1)
}
リスト5 phplesson/chap19/HandballPlayer.php

 (1)でuseを使ってThrowTraitトレイトを組み込んでいます。

 なお、ハンドボールは道具を使いませんので、プロパティとしては何も記述していません。

複数トレイトを利用するには

 トレイトを組み込むクラスの最後としてBaseballPlayerクラスを考えます。テニスやハンドボールと違って、野球は「打つ」と「投げる」の両方の動作が含まれていますので、HitTraitトレイトとThrowTraitトレイトの両方を組み込む必要があります。その場合、どのような記述をするのでしょうか。

 実際に見ていきましょう。リスト6のBaseballPlayerクラスを作成してください。

<?php
class BaseballPlayer extends SportsPlayer
{
    use HitTrait, ThrowTrait;  // (1)
 
    //バットを表すプロパティ。
    private $bat;
    //グローブを表すプロパティ。
    private $glove;
}
リスト6 phplesson/chap19/BaseballPlayer.php

 (1)がHitTraitトレイトとThrowTraitトレイトを組み込んだコードです。単に、トレイト名をカンマ区切りで並べるだけです。

トレイトを組み込んだクラスは外からは通常のクラスと同じ

 最後にトレイトを組み込んだ3個のクラスを実際に利用した実行phpファイルを作成しましょう。リスト7のplayers.phpを作成し、実行してください。

<?php
require_once("HitTrait.php");  // (1)
require_once("ThrowTrait.php");  // (1)
require_once("SportsPlayer.php");
require_once("TennisPlayer.php");
require_once("HandballPlayer.php");
require_once("BaseballPlayer.php");
 
$nakano = new TennisPlayer("中野大輔");
$nakano->hit();  // (2)
$nakatani = new HandballPlayer("中谷秀樹");
$nakatani->throw();  // (3)
$nakagami = new BaseballPlayer("中上隆");
$nakagami->hit();  // (4)
$nakagami->throw();  // (5)
リスト7 phplesson/chap19/players.php

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

TennisPlayerがボールを打ちます。
HandballPlayerがボールを投げます。
BaseballPlayerがボールを打ちます。
BaseballPlayerがボールを投げます。

 (2)〜(5)が各Playerクラスのメソッドを実行している部分です。(2)と(4)のhit()メソッドはHitTraitトレイトによって追加されたメソッドですが、実行する側からはトレイトによって追加されたかどうかは分かりません。このように、通常のメソッドと同様に利用できます。(3)と(5)のthrow()メソッドも同様です。

 なお、hit()メソッドの実行結果が1行目と3行目です。ここではクラス名が表示されていますが、これがリスト2の(3)で紹介した__CLASS__定数の働きです。実行結果の2行目と4行目のthrow()メソッドも同様です。

require順に注意

 トレイトを利用する場合、実行クラスではそれらのトレイトが記述されたファイルも読み込んでおく必要があります。リスト7の(1)が該当します。その際、読み込み順に注意してください。トレイトはクラス内で利用するので、クラスファイルの読み込みより先に行っておく必要があります。それは、連載第17回で紹介した継承の際に子クラスよりも親クラスを先に読み込ませておく必要があるのと同様です。

 以下のようにTennisPlayer.phpより後にHitTrait.phpを読み込んだとします。

 :
require_once("TennisPlayer.php");
require_once("HitTrait.php");
 :

 この場合、以下のようにエラーとなるので注意してください。

Fatal error: Trait 'HitTrait' not found in C:\xampp\htdocs\phplesson\chap19\TennisPlayer.php on line 4

トレイトはnewできない

 トレイトに関して、もう1点注意が必要です。それは、インスタンスが生成できない、つまり、newできないことです。トレイトはクラスに似ていますが、あくまでクラスの一部を機能追加できるようにしただけのものなので、クラスとは違います。例えば、以下のようにHitTraitトレイトをnewしようとしたとします。

$hit = new HitTrait();

 すると、以下のエラーになります。

Fatal error: Uncaught Error: Cannot instantiate trait HitTrait in C:\xampp\htdocs\phplesson\chap19\players.php:17 Stack trace: #0 {main} thrown in C:\xampp\htdocs\phplesson\chap19\players.php on line 17

 エラーメッセージにある通り、トレイトのインスタンスは生成できないので注意してください。

コラム「トレイトからトレイトの利用」

 クラスからトレイトを利用できたように、トレイトからトレイトを利用できます。その場合も、クラスと同様に以下のようにuseを記述します。

trait HikeTrait
{
    use WalkTrait;
    
    :
}

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

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

メールマガジン登録

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