trait是一种代码复用机制。
当一个类需要用到另一个类或多个类时,常用的方法有继承、require引入文件并实例化类等。但PHP只支持单继承,require引入并实例化类后,也只能访问其中的public方法。
PHP还提供一种方式,通过trait类,完全将其它类导入到当前类中,导入后可视为当前类的一部分,区别是不同类中,可能存在相同名称的方法,此时可通过设置别名、设置优先级的方法来控制访问。
Trait类与当前使用类、继承的父类之间的调用优先级顺序如下:
当前使用类>Trait类>继承的父类。当存在同名方法时,会根据优先级覆盖掉同名的类。
trait使用示例:
insteadod关键字:
当引用的多个类中,包含相同的方法名时,可通过 insteadof 关键字设置优先级
as关键字:
当引用的多个类中,包含相同的方法名时,可通过 as 关键字设置别名,然后在类中重写重名的方法,实现每个方法都能正常使用
//trait 是一种代码复用机制
//定义可复用类 TraitA
trait TraitA{
//PHP8.2新特性,允许在trait中定义常量
//PHP版本低于8.2,会抛出致命错误,非8.2环境请注释下面使用const定义的常量
const FOO = 'foo';
private const BAR = 'bar';
final const VIM = 'vim';
final protected const RCO = 'rco';
public function foo(){
echo "TraitA's foo method".",";
}
}
//定义可复用类 TraitB
trait TraitB{
public function foo(){
echo "TraitB's foo method".",";
}
}
class MyClass{
//引用的 TraitA 和 TraitB 同时存在 foo 方法,若不处理,程序会抛出致命错误:Trait method TraitB::foo has not been applied..
use TraitA, TraitB{
//使用 as 关键字起别名
TraitA::foo as public TraitAFoo; //新的方法名为 TraitAFoo
TraitB::foo as protected TraitBfoo;
}
//写法二:可分开引用
//use TraitA{ TraitA::foo as public TraitAFoo; }
//use TraitB{ TraitB::foo as public TraitBfoo; }
//在没有使用insteadof关键字设置优先级时,必须重写 foo 方法,否则抛致命错误
//Fatal error: Trait method TraitB::foo has not been applied as MyClass::foo, because of collision with TraitA::foo
public function foo(){
//可在此调用 TraitA 或 TraitB 中的 foo 方法(可看做设置默认foo方法)
//$this->TraitAFoo();
$this->TraitBFoo();
}
}
$myclass=new MyClass();
$myclass->TraitAFoo(); //TraitA's foo method,
$myclass->foo(); //TraitB's foo method,
//PHP8.2新特性,trait中定义常量
echo $myclass::FOO; //foo
echo ",";
echo $myclass::VIM; //vim
在定义trait类时,即使没有继承任何类,也可以在trait类的方法中通过“parent::父方法名”,提前申明要使用的父类方法
在use引用这个trait类时,必须有继承,且继承的父类要包含已经在trait类中声明过的,要使用的父类方法(parent::父方法名)
由此可看出,use引用trait类后,可视作当前类的一部分
打赏