一年多没有写公众号文章了,当然这一年也没有怎么新增关注用户,还好老用户基本没有流失。现在开始重新不定期更新公众号文章,给大家传递最有价值的编程技术。希望大家喜欢,最好能转发支持。
废话不多说,下面进入正文:
PHP是单继承语言,为了使开发人员在不同层次结构内独立的类中复用方法,PHP5.4.0起,PHP实现了一种代码复用的方法Trait,Trait无法自身实例化,通过和Class组合的方式实现多继承。
示例
优先级 派生类>trait>基类
traitA {
publicfunctionsayHello(){
echo"Hello trait\n";
}
publicfunctionsayHi(){
echo"Hi trait\n";
}
}
classB{
publicfunctionsayHello(){
echo"Hello class\n";
}
publicfunctionsayHi(){
echo"Hi class\n";
}
}
classCextendsB{
useA;
publicfunctionsayHello(){
echo"Hello C\n";
}
}
$c =newC();
$c->sayHello();
$c->sayHi();
多个trait,用英文逗号分隔。
traitHello {
publicfunctionsayHello(){
echo"Hello ";
}
}
traitWorld {
publicfunctionsayWorld(){
echo"World";
}
}
classTest{
useHello,World;
publicfunctionsayHelloWorld(){
echo"!\n";
}
}
$test =newTest();
$test->sayHello();
$test->sayWorld();
$test->sayHelloWorld();
解决冲突
traitA {
publicfunctionsayHello(){
echo"Hello A\n";
}
publicfunctionsayHi(){
echo"Hi A\n";
}
}
traitB {
publicfunctionsayHello(){
echo"Hello B\n";
}
publicfunctionsayHi(){
echo"Hi B\n";
}
}
classC{
// 使用insteadof操作符明确指定使用冲突方法中的哪一个
useA,B{
A::sayHelloinsteadofB;
B::sayHiinsteadofA;
}
}
classD{
useA,B{
A::sayHelloinsteadofB;
B::sayHiinsteadofA;
A::sayHiashi;// as操作符为某个方法引入别名,解决多个trait都插入一个同名方法的冲突
}
}
$c =newC();
$c->sayHello();
$c->sayHi();
echo"\n";
$d =newD();
$d->sayHello();
$d->sayHi();
使用as语法调整方法的访问控制
traitHello {
publicfunctionsayHello(){
echo"Hello trait\n";
}
}
classA{
useHello{
Hello::sayHelloasprotected;// 使用as操作符修改sayHello的访问控制
}
}
classB{
useHello{
Hello::sayHelloasprivatesayHi;// 使用as操作符给sayHello引入一个别名并修改别名的访问控制,原版sayHello的访问控制不改变
}
}
$a =newA();
// PHP Fatal error: Uncaught Error: Call to protected method A::sayHello() from context '' in trait5.php:158
$a->sayHello();
$b =newB();
$b->sayHello();
// PHP Fatal error: Uncaught Error: Call to private method B::sayHi() from context '' in trait5.php:162
$b->sayHi();
使用trait组合trait
traitHello {
publicfunctionsayHello(){
echo"Hello ";
}
}
traitWorld {
publicfunctionsayWorld(){
echo"World!\n";
}
}
traitHelloWorld {
useHello,World;
}
classHi{
useHelloWorld;
}
$hi =newHi();
$hi->sayHello();
$hi->sayWorld();
trait使用抽象方法,对组合trait的类施加强制要求
traitHello {
publicfunctionsayHello(){
echo"Hello ".$this->getWorld();
}
// 抽象方法
abstractpublicfunctiongetWorld();
}
classHi{
private$world;
useHello;// 组合trait
// 实现抽象方法
publicfunctiongetWorld(){
return$this->world;
}
publicfunctionsetWorld($val){
$this->world = $val;
}
}
$hi =newHi();
$hi->setWorld("world!\n");
$hi->sayHello();
trait定义静态属性和静态方法
traitCounter {
publicfunctioninc(){
// 静态属性
static$c =;
$c = $c +1;
echo"$c\n";
}
// 静态方法
publicstaticfunctiondoSomething(){
return"Doing Something\n";
}
}
classTest{
useCounter;
}
$test =newTest();
$test->inc();
echo$test::doSomething();
$test->inc();
trait定义属性
traitA {
public$name ='frankphper';
public$age =18;
}
classB{
useA;
public$name ='frankphper';
public$age =28;
}
$b =newB();
echo$b->name;// PHP 7.0.0 后没问题,之前版本是 E_STRICT 提醒
echo"\n";
echo$b->age;// PHP Fatal error: B and A define the same property ($age) in the composition of B. However, the definition differs and is considered incompatible. Class was composed in trait5.php on line 250
echo"\n";
领取专属 10元无门槛券
私享最新 技术干货