加入收藏 | 设为首页 | 会员中心 | 我要投稿 揭阳站长网 (https://www.0663zz.cn/)- 机器学习、行业智能、决策智能、云计算、AI应用!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

PHP中Trait的用法及示例

发布时间:2022-06-30 09:46:02 所属栏目:PHP教程 来源:互联网
导读:PHP是单继承的语言,在PHP 5.4 Traits出现之前,PHP的类无法同时从两个基类继承属性或方法,为了解决这个问题,php出了Trait这个特性。(Traits和Go语言的组合功能有点类似)。 用法:通过在类中使用use关键字声明要组合的Trait名称,而具体某个Trait的声明
  PHP是单继承的语言,在PHP 5.4 Traits出现之前,PHP的类无法同时从两个基类继承属性或方法,为了解决这个问题,php出了Trait这个特性。(Traits和Go语言的组合功能有点类似)。
 
  用法:通过在类中使用use关键字声明要组合的Trait名称,而具体某个Trait的声明使用trait关键词,Trait不能直接实例化。
 
  <?php
   
  trait Drive {
   
      public $carName = 'BMW';
   
      public function driving() {
   
          echo "driving {$this->carName}n";
   
      }
   
  }
   
     
   
  class Person {
   
      public function age() {
   
          echo "i am 18 years oldn";
   
      }
   
  }
   
     
   
  class Student extends Person {
   
      use Drive;
   
      public function study() {
   
          echo "Learn to drive n";
   
      }
   
  }
   
     
   
  $student = new Student();
   
  $student->study();  //输出:Learn to drive  
   
  $student->age();    //输出:i am 18 years old
   
  $student->driving();//输出:driving BMW
  结论:
 
  Student类通过继承Person,有了age方法
 
  通过组合Drive,有了driving方法和属性carName。
 
  如果Trait、基类和本类中都存在某个同名的属性或者方法,最终会保留哪一个呢?通过下面的代码测试一下:
 
  <?php
   
     
   
  trait Drive {
   
      public function hello() {
   
          echo "hello 周伯通n";
   
      }
   
      public function driving() {
   
          echo "周伯通不会开车n";
   
      }
   
  }
   
     
   
  class Person {
   
      public function hello() {
   
          echo "hello 大家好n";
   
      }
   
      public function driving() {
   
          echo "大家都会开车n";
   
      }
   
  }
   
     
   
  class Student extends Person {
   
      use Drive;//trait 的方法覆盖了基类Person中的方法,所以Person中的hello 和driving被覆盖
   
      public function hello() {
   
          echo "hello 新学员n";//当方法或属性同名时,当前类中的方法会覆盖 trait的 方法,所以此处hello会覆盖trait中的
   
          hello
   
      }
   
  }
   
  $student = new Student();
   
  $student->hello();    //输出:hello 新学员
   
  $student->driving();  //输出:周伯通不会开车
  结论:当方法或属性同名时,当前类中的方法会覆盖 trait的 方法,而 trait 的方法又覆盖了基类中的方法。
 
  如果要组合多个Trait,通过逗号分隔 Trait名称:
 
  use Trait1, Trait2;
 
  如果多个Trait中包含同名方法或者属性时,会怎样呢?答案是当组合的多个Trait包含同名属性或者方法时,需要明确声明解决冲突,否则会产生一个致命错误。
 
  <?php
   
  trait Trait1 {
   
      public function hello() {
   
          echo "Trait1::hellon";
   
      }
   
      public function hi() {
   
          echo "Trait1::hin";
   
      }
   
  }
   
     
   
  trait Trait2 {
   
      public function hello() {
   
          echo "Trait2::hellon";
   
      }
   
      public function hi() {
   
          echo "Trait2::hin";
   
      }
   
  }
   
     
   
  class Class1 {  
   
      use Trait1, Trait2;
   
  }
   
     
   
  //输出:Fatal error:  Trait method hello has not been applied, because there are collisions with other trait
   
   methods on Class1 in
  使用insteadof和as操作符来解决冲突,insteadof是使用某个方法替代另一个,而as是给方法取一个别名,具体用法请看代码:
 
  <?php
   
  trait Trait1 {
   
      public function hello() {
   
          echo "Trait1::hello n";
   
      }
   
      public function hi() {
   
          echo "Trait1::hi n";
   
      }
   
  }
   
  trait Trait2 {
   
      public function hello() {
   
          echo "Trait2::hellon";
   
      }
   
      public function hi() {
   
          echo "Trait2::hin";
   
      }
   
  }
   
  class Class1 {
   
      use Trait1, Trait2 {
   
          Trait2::hello insteadof Trait1;
   
          Trait1::hi insteadof Trait2;
   
      }
   
  }
   
     
   
  class Class2 {
   
      use Trait1, Trait2 {
   
          Trait2::hello insteadof Trait1;
   
          Trait1::hi insteadof Trait2;
   
          Trait2::hi as hei;
   
          Trait1::hello as hehe;
   
      }
   
  }
   
     
   
  $Obj1 = new Class1();
   
  $Obj1->hello();
   
  $Obj1->hi();
   
  echo "n";
   
  $Obj2 = new Class2();
   
  $Obj2->hello();
   
  $Obj2->hi();
   
  $Obj2->hei();
   
  $Obj2->hehe();
  输出:
 
  Trait2::hello
   
  Trait1::hi  
   
  Trait2::hello
   
  Trait1::hi  
   
  Trait2::hi
   
  Trait1::hello
   
  <?php
   
  trait Hello {
   
      public function hello() {
   
          echo "hello,我是周伯通n";
   
      }
   
  }
   
  class Class1 {
   
      use Hello {
   
          hello as protected;
   
      }
   
  }
   
  class Class2 {
   
      use Hello {
   
          Hello::hello as private hi;
   
      }
   
  }
   
  $Obj1 = new Class1();
   
  $Obj1->hello(); # 报致命错误,因为hello方法被修改成受保护的
   
     
   
  $Obj2 = new Class2();
   
  $Obj2->hello(); # 输出: hello,我是周伯通,因为原来的hello方法仍然是公共的
   
  $Obj2->hi();  # 报致命错误,因为别名hi方法被修改成私有的
  Uncaught Error: Call to protected method Class1::hello() from context '' in D:webmytestp.php:18
 
  Trait 也能组合Trait,Trait中支持抽象方法、静态属性及静态方法,测试代码如下:
 
  <?php
   
  trait Hello {
   
      public function sayHello() {
   
          echo "Hello 我是周伯通n";
   
      }
   
  }
   
     
   
  trait World {
   
      use Hello;
   
      public function sayWorld() {
   
          echo "hello worldn";
   
      }
   
      abstract public function getWorld();
   
      public function inc() {
   
          static $c = 0;
   
          $c = $c + 1;
   
          echo "$cn";
   
      }
   
      public static function doSomething() {
   
          echo "Doing somethingn";
   
      }
   
  }
   
     
   
  class HelloWorld {
   
      use World;
   
      public function getWorld() {
   
          return 'do you get World ?';
   
      }
   
  }
   
     
   
  $Obj = new HelloWorld();
   
  $Obj->sayHello();
   
  $Obj->sayWorld();
   
  echo $Obj->getWorld() . "n";
   
  HelloWorld::doSomething();
   
  $Obj->inc();
   
  $Obj->inc();
  输出:
 
  Hello 我是周伯通
 
  hello world
 
  do you get World ?
 
  Doing something12

(编辑:揭阳站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读