第10章 オブジェクト指向構文 / 第3回 模擬試験
PHPのトレイトの名前競合に関する次の記述のうち、正しいものはどれか。
複数のトレイトに同名のメソッドがあり競合する場合、`insteadof`で優先するトレイトを指定できる。
正解
トレイトの名前が競合した場合、PHPは自動的に先に定義したトレイトを常に優先する。
トレイトの名前競合は、PHPでは検出されずに実行時エラーになる。
トレイトは名前の競合が起こらないよう、1クラスにつき1つしか使用できない。
解説
複数のトレイトを1つのクラスに取り込んだ際、同名のメソッドが競合すると、PHPはどちらを使うべきか自動では決められずエラーになります。この競合を解決するには、`use TraitA, TraitB { TraitA::method insteadof TraitB; }`のように`insteadof`を使って、どちらのトレイトのメソッドを優先するかを明示的に指定します。
他の選択肢が誤りである理由は次の通りです。
・PHPは競合時に「先に定義したトレイトを自動的に優先する」というような暗黙のルールは持っていません。解決方法を明示しないと、クラス定義の時点でFatal errorになります。
・トレイトの名前競合は、クラスを実際に使う「実行時」ではなく、クラスを定義する時点で即座に検出され、明確なエラーメッセージとともにFatal errorになります。「検出されずに」というのは誤りです。
・1つのクラスに`use TraitA, TraitB;`のように複数のトレイトを取り込むこと自体は可能です。競合が起きるのは、たまたま同名のメソッドを持つトレイトを複数取り込んだ場合に限られます。
例:
```
trait A { public function hello() { return 'A'; } }
trait B { public function hello() { return 'B'; } }
class C {
use A, B {
A::hello insteadof B;
B::hello as helloFromB;
}
}
echo (new C())->hello(); // A
echo (new C())->helloFromB(); // B
```
(参照: 独習PHP 第4版 第10章 オブジェクト指向構文 10.5.4節 名前競合時の挙動 p.529〜531)