元のリンク: http://tabalt.net/blog/php-traits/
PHP は単一継承言語です。PHP 5.4 Traits が登場する前は、PHP クラスは 2 つの基本クラスからプロパティやメソッドを継承できませんでした。同時。 PHP の Trait の結合機能は Go 言語の結合機能と似ていますが、結合する Trait の名前はクラス内で use キーワードを使用して宣言されます。ただし、特定の Trait の宣言には trait キーワードが使用されません。直接インスタンス化されます。具体的な使用方法は以下のコードを参照してください:
<?php trait Drive { public $carName = 'trait'; public function driving() { echo "driving {$this->carName}\n"; } } class Person { public function eat() { echo "eat\n"; } } class Student extends Person { use Drive; public function study() { echo "study\n"; } } $student = new Student(); $student->study(); $student->eat(); $student->driving();
studyeatdriving trait
Trait、基底クラス、このクラスに同名のプロパティやメソッドがあった場合、最終的にどちらが保持されるのでしょうか?次のコードでテストしてください:
<?php trait Drive { public function hello() { echo "hello drive\n"; } public function driving() { echo "driving from drive\n"; } } class Person { public function hello() { echo "hello person\n"; } public function driving() { echo "driving from person\n"; } } class Student extends Person { use Drive; public function hello() { echo "hello student\n"; } } $student = new Student(); $student->hello(); $student->driving();
hello studentdriving from drive
複数のトレイトを組み合わせたい場合は、トレイト名をカンマで区切ります:
use Trait1, Trait2;
<?phptrait Trait1 { public function hello() { echo "Trait1::hello\n"; } public function hi() { echo "Trait1::hi\n"; }}trait Trait2 { public function hello() { echo "Trait2::hello\n"; } public function hi() { echo "Trait2::hi\n"; }}class Class1 { use Trait1, Trait2;}
PHP Fatal error: Trait method hello has not been applied, because there are collisions with other trait methods on Class1 in ~/php54/trait_3.php on line 20
<?phptrait Trait1 { public function hello() { echo "Trait1::hello\n"; } public function hi() { echo "Trait1::hi\n"; }}trait Trait2 { public function hello() { echo "Trait2::hello\n"; } public function hi() { echo "Trait2::hi\n"; }}class Class1 { use Trait1, Trait2 { Trait2::hello insteadof Trait1; Trait1::hi insteadof Trait2; }}class Class2 { use Trait1, Trait2 { Trait2::hello insteadof Trait1; Trait1::hi insteadof Trait2; Trait2::hi as hei; Trait1::hello as hehe; }}$Obj1 = new Class1();$Obj1->hello();$Obj1->hi();echo "\n";$Obj2 = new Class2();$Obj2->hello();$Obj2->hi();$Obj2->hei();$Obj2->hehe();
Trait2::helloTrait1::hiTrait2::helloTrait1::hiTrait2::hiTrait1::hello
<?php trait Hello { public function hello() { echo "hello,trait\n"; } } class Class1 { use Hello { hello as protected; } } class Class2 { use Hello { Hello::hello as private hi; } } $Obj1 = new Class1(); $Obj1->hello(); # 报致命错误,因为hello方法被修改成受保护的 $Obj2 = new Class2(); $Obj2->hello(); # 原来的hello方法仍然是公共的 $Obj2->hi(); # 报致命错误,因为别名hi方法被修改成私有的
<?phptrait Hello { public function sayHello() { echo "Hello\n"; }}trait World { use Hello; public function sayWorld() { echo "World\n"; } abstract public function getWorld(); public function inc() { static $c = 0; $c = $c + 1; echo "$c\n"; } public static function doSomething() { echo "Doing something\n"; }}class HelloWorld { use World; public function getWorld() { return 'get World'; }}$Obj = new HelloWorld();$Obj->sayHello();$Obj->sayWorld();echo $Obj->getWorld() . "\n";HelloWorld::doSomething();$Obj->inc();$Obj->inc();