php中trait语法的在多继承上的使用

php中trait语法的在多继承上的使用

周赒
2021-11-28 / 1 评论 / 56 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2021年12月01日,已超过1066天没有更新,若内容或图片失效,请留言反馈。

官方说明:

  PHP 实现了一种代码复用的方法,称为 trait。
  首先我们了解trait语法之前,我们先看看的php的继承 。据我们了解,php继承是单继承,不是多继承的,就是一个类只能继承一个父级类,无法继承多类。为了实现多继承,trait就应运而生了 。
  当然实现多继承,不止有trait一种方法你也可以使用接口(interface),我们今天只说trait语法,
  官方文档: 地址

优先级

  从基类继承的成员会被 trait 插入的成员所覆盖。优先顺序是来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法。
  

trait 方法又覆盖了基类中的实例
class Base {
    public function sayHello() {
        echo 'Hello BASE ';
    }
}
trait SayWorld {
    public function sayHello() {
        // parent::sayHello();
        echo 'SayWorld!';
    }
}
class MyHelloWorld extends Base {
    use SayWorld;
  
}
$o = new MyHelloWorld();
$o->sayHello();
// 输出内容  SayWorld ; 输出了trait 的方法属性

  

当前类的成员覆盖了 trait 的方法实例
class Base {
    public function sayHello() {
        echo 'Hello BASE ';
    }
}
trait SayWorld {
    public function sayHello() {
        // parent::sayHello();
        echo 'SayWorld!';
    }
}

// 这样相当于本类继承了两个类
class MyHelloWorld extends Base {
    use SayWorld;
    public function sayHello()
    {
        echo 'MyHelloWorld!';
    }
}
$o = new MyHelloWorld();
$o->sayHello();
// 输出内容  MyHelloWorld; 输出了本类的方法属性

  

多继承的实现实例:
class Base {
    public function sayHello() {
        echo 'Hello BASE ';
    }
    public function doThing() {
        echo 'doingvBASE ';
    }
}
trait SayWorld {
    public function sayHello() {
        // parent::sayHello();
        echo 'SayWorld!';
    }
    public function sayBey() {
        // parent::sayHello();
        echo 'SayWorld!';
    }
}
class MyHelloWorld extends Base {
    use SayWorld;
    public function sayHello()
    {
        echo 'MyHelloWorld!';
    }
}
$o = new MyHelloWorld();
$o->sayHello();
echo "<br/>" ;
$o->doThing();
echo "<br/>" ;
$o->sayBey();
echo "<br/>" ;

// MyHelloWorld!
// doingvBASE
// SayWorld!
我即可以使用trait 的方法 也可以使用父类的方法 ; 相当于我同时继承了两个类 ; 这是就是多继承的简单实现
多个 trait

  通过逗号分隔,在 use 声明列出多个 trait,可以都插入到一个类中。

trait Cat {
    public function catEat() {
        // parent::sayHello();
        echo '吃鱼!';
    }
    public function catHobby() {
        // parent::sayHello();
        echo '爱捉老鼠!';
    }
}
trait Dog {
    public function dogEat() {
        echo '吃骨头!';
    }
    public function hobby() {
        // parent::sayHello();
        echo '看家护院!';
    }
}
class Pets  {
    use Cat,Dog;
    public function info()
    {
        echo 'Pets!';
    }
}
$o = new Pets();
$o->info();
echo "<br/>" ; // Pets!
$o->catEat();  // 吃鱼!
echo "<br/>" ;
$o->dogEat();  // 吃骨头!
echo "<br/>" ; 
// Pets!
// 吃鱼!
// 吃骨头!
冲突的解决

  如果两个 trait 都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。
  为了解决多个 trait 在同一个类中的命名冲突,需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个。
  以上方式仅允许排除掉其它方法,as 操作符可以 为某个方法引入别名。 注意,as 操作符不会对方法进行重命名,也不会影响其方法

实例:
trait Cat {
    public function eat() {
        // parent::sayHello();
        echo '吃鱼!';
    }
    public function hobby() {
        // parent::sayHello();
        echo '爱捉老鼠!';
    }
}
trait Dog {
    public function eat() {
        echo '吃骨头!';
    }
    public function hobby() {
        // parent::sayHello();
        echo '看家护院!';
    }
}
class Pets  {
    use Cat,Dog{
        Cat::eat insteadof Dog; // cat .eat 替代 DOG.eat
        Dog::hobby insteadof Cat;  // hobby  继承 DOG
    }
    /*
  use Cat,Dog{
      Cat::eat as cEat;   // 将 重名的方法 设置不重名 
      Dog::hobby as cHobby;
  }
  */

    public function info()
    {
        echo 'Pets!';
    }
}
$o = new Pets();
$o->info();
echo "<br/>" ;
$o->eat();
echo "<br/>" ;
$o->hobby();
echo "<br/>" ;
//Pets!
// 吃鱼!
// 看家护院!
注意:

  Trait 定义了一个属性后,类就不能定义同样名称的属性,否则会产生 fatal error。 有种情况例外:属性是兼容的(同样的访问可见度、初始默认值)。

示例 # 解决冲突
trait PropertiesTrait {
    public $same = true;
    public $different = false;
}
class PropertiesExample {
    use PropertiesTrait;
    public $same = true;
    public $different = true; // 致命错误
}

  更多的详细语法详见官方文档 : 地址

0

评论 (1)

取消
  1. 头像
    周赒 作者
    Windows 10 · Google Chrome

    画图

    回复