laravel5.1によく出てくるTraitとは、そもそも何なのか?
Q1, PHPのトレイトという機能は、どういうものなの?
A1, クラスとは独立して、メソッド(クラス関数)やプロパティ(クラス変数)を単独で定義できる。
使いたいクラスで、使いたいメソッドだけuseすればいい(逆にuseされずに、トレイト単体では実行できない。dllファイルに近い?)
クラスの継承に近い感じ(PHPでは多重継承できないので、複数のtraitを使って実現する)
http://qiita.com/sasakure-kei@github/items/212637b2f32197441a3a
Q2, 具体的には、どうやって使うの?
A2, 簡単なサンプルは以下の通り
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<?php // メソッドだけのトレイトを定義 trait HelloTrait { public function say() { return 'hello, world'; } } // 親クラス class OyaClass { // トレイトだけを取り込む use HelloTrait; } // 子クラス class koClass extends OyaClass { // 何も実装無し! } // 子クラスのインスタンス生成 $ko = new koClass(); // 親クラスがuseしたトレイトのメソッドを実行 echo $ko->say(); //画面にhello, worldと表示される |
Q3, traitは複数useできるけど、全く同じメソッド名があったら、どうなるの?
A3, バッティング(どちらを適用していいのか分からない)して、単純にエラーになる。
Fatal error: Trait method say has not been applied, because there are collisions with other trait methods on OyaClass
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<?php // メソッドだけのトレイトを定義 trait HelloTrait { public function say() { return 'hello'; } } trait WorldTrait { public function say() { return 'hello'; } } // 親クラス class OyaClass { // トレイトだけを取り込む use HelloTrait; use WorldTrait; } // 子クラス class koClass extends OyaClass { // 何も実装無し! } // 子クラスのインスタンス生成 $ko = new koClass(); // 親クラスがuseしたトレイトのメソッドを実行 echo $ko->say(); // 同名のメソッドがあるため、エラーになる |
Q4, なんとかならないの、これ?
A4, 子クラスがuseしたトレイトのメソッドを優先(上書き)して実行してくれる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<?php // メソッドだけのトレイトを定義 trait HelloTrait { public function say() { return 'hello'; } } trait WorldTrait { public function say() { return 'world'; } } // 親クラス class OyaClass { // トレイトだけを取り込む use HelloTrait; } // 子クラス class koClass extends OyaClass { // sayメソッドは上書きされる! use WorldTrait; } // 子クラスのインスタンス生成 $ko = new koClass(); // 同名メソッドがあった場合は、 // 子クラスがuseしたトレイトのメソッドを優先(上書き)して実行 echo $ko->say(); // worldと表示される |
Q5, なるほど、変更したいメソッドがあったら、元のtraitをコピペして、自作traitを作って上書きすればいいのか!
A5, 正解! そして自作traitファイルを生成しなくても、使うクラス内で再定義(上書き)できる
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<?php // メソッドだけのトレイトを定義 trait HelloTrait { public function say() { return 'hello'; } } // 親クラス class OyaClass { // トレイトのsayメソッドを、このブロック内だけ_sayと別名にする use HelloTrait{say as _say;} // ここでsayメソッドを再定義できる!! public function say() { // 完全上書き //return "ore, ore!!"; // 元のsayメソッドに追加文字列 return $this->_say() . " It's ME!!"; } } // 子クラス class koClass extends OyaClass { // 相変わらず、何も定義しない。 } // 子クラスのインスタンス生成 $ko = new koClass(); // OyaClassで再定義されたsayメソッドが実行される echo $ko->say(); |