杉哥的个人博客

PHP Trait特性

php类的单继承性,无法同时从两个基类中继承属性和方法,为了解决这个问题,使用Trait特性解决.

Trait是一种代码复用技术,为PHP的单继承限制提供了一套灵活的代码复用机制.

用法:通过在类中使用use 关键字,声明要组合的Trait名称,具体的Trait的声明使用Trait关键词.  注意:Trait不能实例化

示例:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<?php
trait Dog{
public function dog(){
echo 'This trair dog';
}
}
trait Fish{
public function fish(){
echo 'This trair fish';
}
}
class Animal{
public function name(){
echo 'This is animal';
}
}
class Cat extends Animal{
use Dog,Fish;
public function eat(){
echo 'This is animal cat eat';
}
}
$data = new Cat();
$data->name();//This is animal
echo '<pre>';
$data->eat();//This is animal cat eat
echo '<pre>';
$data->dog();//This trair dog
echo '<pre>';
$data->fish();//This trair fish
<?php trait Dog{ public function dog(){ echo 'This trair dog'; } } trait Fish{ public function fish(){ echo 'This trair fish'; } } class Animal{ public function name(){ echo 'This is animal'; } } class Cat extends Animal{ use Dog,Fish; public function eat(){ echo 'This is animal cat eat'; } } $data = new Cat(); $data->name();//This is animal echo '<pre>'; $data->eat();//This is animal cat eat echo '<pre>'; $data->dog();//This trair dog echo '<pre>'; $data->fish();//This trair fish
<?php
trait Dog{
    public function dog(){
    echo 'This trair dog';
    }
}

trait Fish{
    public function fish(){
    echo 'This trair fish';
    }
}


class Animal{
    public function name(){
        echo 'This is animal';
    }
}

class Cat extends Animal{
    use Dog,Fish;
    public function eat(){
        echo 'This is animal cat eat';
    }
}

$data = new Cat();
$data->name();//This is animal
echo '<pre>';
$data->eat();//This is animal cat eat
echo '<pre>';
$data->dog();//This trair dog
echo '<pre>';
$data->fish();//This trair fish

 

一个类可以组合多个Trait,通过逗号相隔,如下

use trait1,trait2

当方法或属性同名时,当前类中的方法会覆盖 trait的 方法,而 trait 的方法又覆盖了基类中的方法。

答案是当组合的多个Trait包含同名属性或者方法时,需要明确声明解决冲突,否则会产生一个致命错误。

使用insteadof和as操作符来解决冲突,insteadof是使用某个方法替代另一个,而as是给方法取一个别名,具体用法:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<?php
trait Trait1 {
public function hello() {
echo "Trait1::hello\n";
}
public function hi() {
echo "Trait1::hi\n";
}
}
trait Trait2 {
public function hello() {
echo "Trait2::hello\n";
}
public function hi() {
echo "Trait2::hi\n";
}
}
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();
<?php trait Trait1 { public function hello() { echo "Trait1::hello\n"; } public function hi() { echo "Trait1::hi\n"; } } trait Trait2 { public function hello() { echo "Trait2::hello\n"; } public function hi() { echo "Trait2::hi\n"; } } 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();
<?php
trait Trait1 {
  public function hello() {
    echo "Trait1::hello\n";
  }
  public function hi() {
    echo "Trait1::hi\n";
  }
}
trait Trait2 {
  public function hello() {
    echo "Trait2::hello\n";
  }
  public function hi() {
    echo "Trait2::hi\n";
  }
}
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();