
php是单继承的语言,在php 5.4 traits出现之前,php的类无法同时从两个基类继承属性或方法,为了解决这个问题,php出了trait这个特性。(traits和go语言的组合功能有点类似)
用法:通过在类中使用use关键字声明要组合的Trait名称,而具体某个Trait的声明使用trait关键词,Trait不能直接实例化。
<?php
trait 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。
立即学习“PHP免费学习笔记(深入)”;
如果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包含同名属性或者方法时,需要明确声明解决冲突,否则会产生一个致命错误。
<?php
trait 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是给方法取一个别名,具体用法请看代码:
<?php
trait 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::hello Trait1::hi Trait2::hello Trait1::hi Trait2::hi Trait1::hello
<?php
trait 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中支持抽象方法、静态属性及静态方法,测试代码如下:
<?php
trait 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 world do you get World ? Doing something12
以上就是PHP中Trait的用法及示例的详细内容,更多请关注php中文网其它相关文章!
 
                        
                        每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
 
                 
                                
                                 收藏
收藏
                                                                             
                                
                                 收藏
收藏
                                                                             
                                
                                 收藏
收藏
                                                                            Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号