トレイトの作成が一通りできたところで、次にトレイトを利用する方法を解説します。
ここまでに作成したトレイトを各クラスに組み込んでいきましょう。まず、「打つ」を表すHitTraitトレイトを組み込んだTennisPlayerクラスを作成します。
<?php class TennisPlayer extends SportsPlayer { use HitTrait; // (1) //ラケットを表すプロパティ。 private $racket; }
トレイトを組み込んでいるコードが(1)です。トレイトをクラスに組み込むには以下のように記述します。
use トレイト名;
なお、TennisPlayerクラスの他のメンバですが、ここではラケットを表すプロパティのみを記述しています。他に必要なプロパティやメソッドがあれば、ここに追記していきますが、トレイトの解説には不要なので省略しています。
同様に、「投げる」を表すThrowTraitトレイトを組み込んだHandballPlayerクラスを作成しましょう。
<?php class HandballPlayer extends SportsPlayer { use ThrowTrait; // (1) }
(1)でuseを使ってThrowTraitトレイトを組み込んでいます。
なお、ハンドボールは道具を使いませんので、プロパティとしては何も記述していません。
トレイトを組み込むクラスの最後としてBaseballPlayerクラスを考えます。テニスやハンドボールと違って、野球は「打つ」と「投げる」の両方の動作が含まれていますので、HitTraitトレイトとThrowTraitトレイトの両方を組み込む必要があります。その場合、どのような記述をするのでしょうか。
実際に見ていきましょう。リスト6のBaseballPlayerクラスを作成してください。
<?php class BaseballPlayer extends SportsPlayer { use HitTrait, ThrowTrait; // (1) //バットを表すプロパティ。 private $bat; //グローブを表すプロパティ。 private $glove; }
(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)
実行結果は以下の通りです。
TennisPlayerがボールを打ちます。 HandballPlayerがボールを投げます。 BaseballPlayerがボールを打ちます。 BaseballPlayerがボールを投げます。
(2)〜(5)が各Playerクラスのメソッドを実行している部分です。(2)と(4)のhit()メソッドはHitTraitトレイトによって追加されたメソッドですが、実行する側からはトレイトによって追加されたかどうかは分かりません。このように、通常のメソッドと同様に利用できます。(3)と(5)のthrow()メソッドも同様です。
なお、hit()メソッドの実行結果が1行目と3行目です。ここではクラス名が表示されていますが、これがリスト2の(3)で紹介した__CLASS__定数の働きです。実行結果の2行目と4行目のthrow()メソッドも同様です。
トレイトを利用する場合、実行クラスではそれらのトレイトが記述されたファイルも読み込んでおく必要があります。リスト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
トレイトに関して、もう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.