PHP中的Trait类

        通俗来讲, Trait类不是类,无法直接使用new关键词来创建对象。

        传统的PHP类是单一继承模式,即每个类只能继承一个父类。

        Trait类的出现让PHP类可以继承多个“父类”。


一、如何使用:

        定义一个Class :

Class cDemo
{
    public function cfun()
    {
        return __METHOD__;
    }
}

        定义两个Trait类:

Trait tDemo1
{
    public function fun1()
    {
        return __METHOD__;
    }
}
 
Trait tDemo2
{
    public function fun2()
    {
        return __METHOD__;
    }
}

        接下来使用一个class 来继承上面的自定义的类

class myClass extends cDemo
{
    // 引用Trait类
    use tDemo1, tDemo2;
}
 
// 实例化类
$obj = new myClass();
 
// 调用父类方法
echo $obj->cfun();  // cDemo::cfun  这个是父类cDemo中定义的方法
 
// 调用Trail中的方法
echo $obj->fun1(); // tDemo1::fun1
echo $obj->fun2(); // tDemo2::fun2

二、注意事项

        1. 优先级关系 本类中的方法 > Trait中的方法 > 父类中的方法

        2. 当一个类继承了多个Trail,且多个Trait中都包含相同的方法时,调用此方法则会报错;解决方案:

        使用 insteadof 关键字和 as 关键字  (insteadof 是进行替代,而as是给它取别名)

trait trait1{
    public function eat(){
        echo "This is trait1 eat";
    }
    public function drive(){
        echo "This is trait1 drive";
    }
}
trait trait2{
    public function eat(){
        echo "This is trait2 eat";
    }
    public function drive(){
        echo "This is trait2 drive";
    }
}
class cat{
    use trait1,trait2{
        trait1::eat insteadof trait2;
        trait1::drive insteadof trait2;
    }
}
class dog{
    use trait1,trait2{
        trait1::eat insteadof trait2;
        trait1::drive insteadof trait2;
        trait2::eat as eaten;
        trait2::drive as driven;
    }
}

$cat = new cat();
$cat->eat();        //This is trait1 eat
$cat->drive();      //This is trait1 drive  

$dog = new dog();
$dog->eat();        //This is trait1 eat
$dog->drive();      //This is trait1 drive
$dog->eaten();      //This is trait2 eat
$dog->driven();     //This is trait2 drive

        如果两个 trait 都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。

        为了解决多个 trait 在同一个类中的命名冲突,需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个。

        以上方式仅允许排除掉其它方法,as 操作符可以 为某个方法引入别名。 注意,as 操作符不会对方法进行重命名,也不会影响其方法。


        as 还可以修改方法的访问控制

trait Animal{
    public function eat(){
        echo "This is Animal eat";
    }
}

class Dog{
    use Animal{
        eat as protected;
    }
}
class Cat{
    use Animal{
        Animal::eat as private eaten;
    }
}
$dog = new Dog();
$dog->eat();//报错,因为已经把eat改成了保护

$cat = new Cat();
$cat->eat();//正常运行,不会修改原先的访问控制
$cat->eaten();//报错,已经改成了私有的访问控制

        Trait也可以互相组合,还可以使用抽象方法,静态属性,静态方法等,实例如下

trait Cat{
    public function eat(){
        echo "This is Cat eat";
    }
}

trait Dog{
    use Cat;
    public function drive(){
        echo "This is Dog drive";
    }
    abstract public function getName();
    
    public function test(){
        static $num=0;
        $num++;
        echo $num;
    }
    
    public static function say(){
        echo "This is Dog say";
    }
}
class animal{
    use Dog;
    public function getName(){
        echo "This is animal name";
    }
}

$animal = new animal();
$animal->getName();            //This is animal name

$animal->eat();                //This is Cat eat

$animal->drive();              //This is Dog drive  

$animal::say();                //This is Dog say

$animal->test();               //1

$animal->test();               //2


参考:

        PHP中Trait详解及其应用

        


冷暖自知一抹茶ck
请先登录后发表评论
  • 最新评论
  • 总共0条评论