PHP trait使用

发布时间 2023-05-09 11:46:51作者: 老夫聊fa少年狂

一、 trait、继承、实例化三者的区别

对于当前一个类需要用到另一个或多个类的方法的情况,我们一般会想到的方式有继承、直接实例化另外一个或多个类等等的方法,来对比一下这些方法和Trait类的区别:

  1. 继承:对于继承,可以完美地复用另一个类的一些方法,但是对于需要复用多个类的方法时,PHP是不支持多继承的,而且只能访问public和protected方法
  2. 直接实例化:我们也可以在当前类中直接实例化要用到的A类与B类,但是这种方法在控制访问范围反面,只允许访问A、B类中public的方法
  3. Trait:使用Trait类则完全将A、B两个类的方法导入到当前类中,可以视为当前类的一部分,唯一区别是可以存在于当前类同名的方法,此时由优先级顺序来控制

二、 Trait类的优先级控制

  1. 当前使用类 > Trait类 > 继承的基类
  2. 当存在同名方法时,会根据优先级覆盖掉同名的类

三、 多个Trait类的冲突控制

在PHP中,如果当前类use了两个Trait类,同时两个trait类都存在一个同名的方法,此时如果没有明确解决冲突将会产生一个致命错误。对于这种情况,PHP官方给出了两个解决方案:

  1. insteadof关键字:通过该关键字指定方法名冲突时该使用哪个Trait类的方法,即:
    如果C类use了A、B两个Trait类,且A、B两个类都存在a、b方法,则在C类use A、B类时使用insteadof声明冲突的解决方法即可:
    // An highlighted block
    use A, B {
      B::a insteadof A; //a方法冲突时使用B类的a方法而不使用A类的a方法
      A::b insteadof B; //b方法冲突时使用A类的b方法而不使用B类的b方法
    }
    
  2. as关键字:通过as关键字将同名方法指定为一个别名,且仅作用于当前类中:
    use A, B {
      B::a as c; //声明B类的a方法为c,作用于该类
      A::b as d; //声明A类的b方法为d,作用于该类
    }
    

四、 举个栗子

class Base{
	  public function sayHello(){
	    echo "hello ";
	  }
}

trait SayWorld{
	  public function sayHello(){
	    parent::sayHello();
	    echo "world".PHP_EOL;
	  }
}

trait SayWorld2{
	  public function sayHello2(){
	    echo "PHP".PHP_EOL;
	  }
}

class MyHelloWorld extends Base{
  	use SayWorld,SayWorld2;
}

$s = new MyHelloWorld();
$s->sayHello();
$s->sayHello2();