您好,欢迎访问一九零五行业门户网

PHP中Trait的用法及示例

php是单继承的语言,在php 5.4 traits出现之前,php的类无法同时从两个基类继承属性或方法,为了解决这个问题,php出了trait这个特性。(traits和go语言的组合功能有点类似)
用法:通过在类中使用use关键字声明要组合的trait名称,而具体某个trait的声明使用trait关键词,trait不能直接实例化。
<?phptrait drive { public $carname = 'bmw'; public function driving() { echo "driving {$this->carname}\n"; }} class person { public function age() { echo "i am 18 years old\n"; }} class student extends person { use drive; public function study() { echo "learn to drive \n"; }} $student = new student();$student->study(); //输出:learn to drive $student->age(); //输出:i am 18 years old$student->driving();//输出:driving bmw
结论:
student类通过继承person,有了age方法
通过组合drive,有了driving方法和属性carname。
如果trait、基类和本类中都存在某个同名的属性或者方法,最终会保留哪一个呢?通过下面的代码测试一下:
<?php trait drive { public function hello() { echo "hello 周伯通\n"; } public function driving() { echo "周伯通不会开车\n"; }} class person { public function hello() { echo "hello 大家好\n"; } public function driving() { echo "大家都会开车\n"; }} class student extends person { use drive;//trait 的方法覆盖了基类person中的方法,所以person中的hello 和driving被覆盖 public function hello() { echo "hello 新学员\n";//当方法或属性同名时,当前类中的方法会覆盖 trait的 方法,所以此处hello会覆盖trait中的 hello }} $student = new student();$student->hello(); //输出:hello 新学员$student->driving(); //输出:周伯通不会开车
结论:当方法或属性同名时,当前类中的方法会覆盖 trait的 方法,而 trait 的方法又覆盖了基类中的方法。
如果要组合多个trait,通过逗号分隔 trait名称:
use trait1, trait2;
如果多个trait中包含同名方法或者属性时,会怎样呢?答案是当组合的多个trait包含同名属性或者方法时,需要明确声明解决冲突,否则会产生一个致命错误。
<?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;} //输出:fatal error: trait method hello has not been applied, because there are collisions with other trait methods on class1 in
使用insteadof和as操作符来解决冲突,insteadof是使用某个方法替代另一个,而as是给方法取一个别名,具体用法请看代码:
<?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::hi trait2::hellotrait1::hi trait2::hitrait1::hello
<?phptrait hello { public function hello() { echo "hello,我是周伯通\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,我是周伯通,因为原来的hello方法仍然是公共的$obj2->hi(); # 报致命错误,因为别名hi方法被修改成私有的
uncaught error: call to protected method class1::hello() from context '' in d:\web\mytest\p.php:18
trait 也能组合trait,trait中支持抽象方法、静态属性及静态方法,测试代码如下:
<?phptrait hello { public function sayhello() { echo "hello 我是周伯通\n"; }} trait world { use hello; public function sayworld() { echo "hello 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 'do you get world ?'; }} $obj = new helloworld();$obj->sayhello();$obj->sayworld();echo $obj->getworld() . "\n";helloworld::dosomething();$obj->inc();$obj->inc();
输出
hello 我是周伯通hello worlddo you get world ?doing something12
以上就是php中trait的用法及示例的详细内容。
其它类似信息

推荐信息