PHP – 特性



在 PHP 中,一个类只能继承自一个父类,PHP 中未定义多重继承。PHP 中的特性是为了克服此限制而引入的。您可以在特性中定义一个或多个方法,这些方法可以在各种独立类中自由重用。

语法

“trait”关键字按以下语法使用:

trait mytrait {
   function method1() {
      /*function body*/
   }

   function method2() {
      /*function body*/
   }
}

为了能够调用特性中的方法,需要使用 use 关键字将其提供给另一个类。

示例

特性类似于类,但仅用于以细粒度和一致的方式对功能进行分组。无法单独实例化特性。

<?php
   trait mytrait {
      public function hello() {
         echo "Hello World from " . __TRAIT__ . "";
      }
   }
   class myclass {
      use mytrait;
   }
   $obj = new myclass();
   $obj->hello();
?>

它将产生以下输出

Hello World from mytrait

示例

特性可以在多个类中使用。以下示例具有一个包含 avg() 函数的 mytrait。它用于 marks 类中。percent() 方法在内部调用特性中的 avg() 函数。

请查看以下示例:

<?php
   trait mytrait {
      function avg($x, $y) {
         return ($x+$y)/2;
      }
   }
   class marks {
      use mytrait;
      private int $m1, $m2;
      function __construct($x, $y) {
         $this->m1 = $x;
         $this->m2 = $y;
      }
      function percent():float {
         return $this->avg($this->m1, $this->m2);
      }
   }
   $obj = new marks(50, 60);
   echo "percentage: " . $obj->percent();
?>

它将产生以下输出

percentage: 55

使用多个特性

一个类可以使用多个特性。这里我们有两个特性,每个特性都有一个函数,分别执行两个数字的加法和乘法。两者都用于第三个类中。

<?php
   trait addition {
      function add($x, $y) {
         return $x+$y;
      }
   }

   trait multiplication {
      function multiply($x, $y) {
         return $x*$y;
      }
   }

   class numbers {
      use addition, multiplication;
      private int $m1, $m2;
      function __construct($x, $y) {
         $this->m1 = $x;
         $this->m2 = $y;
      }
      function calculate():array {
         $arr = [$this->add($this->m1, $this->m2), $this->multiply($this->m1, $this->m2)];
         return $arr;
      }
   }

   $obj = new numbers(50, 60);
   $res = $obj->calculate();
   echo "Addition: " . $res[0] . PHP_EOL;
   echo "Multiplication: " . $res[1] . PHP_EOL;
?>

它将产生以下输出

Addition: 110
Multiplication: 3000

覆盖特性函数

当一个类使用某个特性时,它的函数就像子类继承父方法一样对它可用。也可以覆盖特性函数。

<?php
   trait mytrait {
      public function sayHello() {
         echo 'Hello World!';
      }
   }

   class myclass {
      use mytrait;
      public function sayHello() {
         echo 'Hello PHP!';
      }
   }

   $o = new myclass();
   $o->sayHello();
?>

它将产生以下输出

Hello PHP!

“insteadof”关键字

有时,两个或更多特性可能具有相同名称的函数。因此,在类中使用它们会产生模棱两可的情况。PHP 提供 insteadof 关键字来告诉解析器您打算使用哪个特性的函数。

<?php
   trait mytrait {
      public function sayHello() {
         echo 'Hello World!';
      }
   }

   trait newtrait {
      public function sayHello() {
         echo 'Hello PHP!';
      }
   }

   class myclass {
      use mytrait, newtrait{
         newtrait::sayHello insteadof mytrait;
      }
   }

   $o = new myclass();
   $o->sayHello();
?>

它将产生以下输出

Hello PHP!

特性函数的别名

如果希望能够调用来自两个特性的函数,即使它们具有相同名称的函数,也可以通过为其中一个指定别名作为解决方法。

示例

在以下示例中,我们将 mytrait 中的 sayHello() 称为 hello():

<?php
   trait mytrait {
      public function sayHello() {
         echo 'Hello World!' . PHP_EOL;
      }
   }

   trait newtrait {
      public function sayHello() {
         echo 'Hello PHP!' . PHP_EOL;
      }
   }

   class myclass {
      use mytrait, newtrait{
         mytrait::sayHello as hello;
         newtrait::sayHello insteadof mytrait;
      }
   }

   $o = new myclass();
   $o->hello();
   $o->sayHello();
?>

它将产生以下输出

Hello World!
Hello PHP!
广告