美文网首页
Trait的五种应用场景

Trait的五种应用场景

作者: xuxin2020 | 来源:发表于2021-03-23 16:55 被阅读0次
  • php中继承是单继承,如果某个类有成员要被其他类使用,就需要称为其他类的父类才行,这样可能会导致继承链会长,合适吗?

引入:继承的角度出发,继承链可以解决问题,但是的确效率会打折扣,同时,如果某些功能是共性使用,但是并不符合(不属于同一类)继承条件,那么使用继承也有所违背面上对象规则,此时可以使用php提供的另外一种代码复用技术trait

一:代码复用

二:在继承上下文中的应用

三:实现功能扩展

四:在trait组合中命名冲突的解决方案

五:trait和interface的组合

1.代码复用

定义:trait是为类似php的单继承语言而准备的一种代码复用机制,trait可以避免继承语言为了复用而不得不继承的尴尬,让面向对象更加纯粹

1-1、trait是一种类似class的关键字

 定义trait
 trait show{
 }

1-2、trait内部可以像类一样拥有成员属性(包含静态),成员方法(包含静态),但不能有常量
示例:

trait uSername //定义trait
{
  public  function show()  //定义一个公用的方法
 {
   return  '姓名:'.$this->username.'|国家:'.$this->nation.'|电话:'.$this->mobile;
   //返回一段用户信息
 }
 public  static  function show1()  //定义一个show1静态方法
 {
  printf('<pre>%s</pre>',print_r(get_class_vars(__CLASS__),true));
  //打印当前类返回的数组get_class_vars
  }
}

class  User  //定义一个User类
{
   use uSername;  //调用trait
   protected $username ='曹操';  //为隐私属性赋值
   public $nation ='魏国';  //为公用属性赋值
   private $mobile ='13666666666';//为私有属性赋值
}
echo (new  User)->show();  //实例化User调用trait

class  User1  //定义一个User1类
{
   use uSername;  //调用trait
   public $username ='刘备';  //为公用属性赋值
   private $nation ='蜀国';  //为私有属性赋值
   protected $mobile ='13555555555';  //为隐私属性赋值
 }
echo (new  User1)->show();  //实例化User调用trait

User::show1();  //使用静态实例化调用trait中的show1方法

User1::show1();  //使用静态实例化调用trait中的show1方法

示例图


image

2:在继承上下文中的应用

在实例中创建了trait及抽象类和子类,知道了通过实例化子类对程序的执行顺序。
示例:

trait aTtribute  创建trait
{
  public  static  function show()  创建一个静态的show方法
  {
    echo '我是trait->show<br>';
    return  Attribute1::show();  返回一条字符串
  }
}
abstract  class  Attribute1  抽象类不可以被实例化
{
  use aTtribute;  调用trait
  public  static  function show()  //抽象类中创建一个静态的show方法
 { 
    返回trait的show方法
    return  '我是父类show<br>';
  }
}
class  Attribute2  extends  Attribute1  //创建Attribute的子类
{
   use aTtribute;  //调用trait
   public  static  function show()  //创建一个静态的show方法
   {
      echo '我是子类show<br>';
      return aTtribute::show();  //返回抽象类的的show方法
   }
 }

echo Attribute2::show();  //输出Attribute2子类的show()方法
//子类同名成员优先大于父类同名成员
//如果子类、父类、trait中存在同名方法的时候,而trait在子类中调用,先调用子类->在调用trait->父类
image

3:实现功能扩展

示例:

trait tDemo
  {
    //1.打印所有属性
    public  function getProps()
    {
     printf('<pre>%s</pre>',print_r(get_class_vars(__CLASS__),true));
    }
 }

trait tDemo1
{
        //2.打印所有方法
    public  function getMethost()
   {
       printf('<pre>%s</pre>',print_r(get_class_methods(__CLASS__),true));
    }
  //__CLASS__:返回当前类的名称字符串
  //self:返回当前类的引用
}

trait tDemo2
{
  use tDemo1,tDemo;
}
class  Users
{
   use tDemo2;
   public $name ='刘备';
   public $nation ='蜀国';
   public  function show()
  {
      return $this->name.':'.$this->nation;
  }
  //扩展这个类的功能
  //添加二个公共方法
}

echo (new  Users)->show();
echo (new  Users)->getProps();
echo (new  Users)->getMethost();

示例图


image

4:在trait组合中命名冲突的解决方案

  • 在trait中有重名的方法,可以使用insteadOf替换将重名的的方法重命名。
  • 格式
    trait名称::重名的方法 as 新的命名;
    trait名称::重名的方法 insteadOf替换 trait名称::重名的方法;
    示例:
trait tDemo
{
    public  static $car =  '汽车';
    public  static  function show()  //定义的了静态show方法`
   {
    return  self::$car;
   }
}
trait tDemo1
{
   public  static $train =  '火车';
  public  static  function show()  //定义的了静态show方法
  {
   return  self::$train;
  }
}
trait tDemo2
{
   use tDemo, tDemo1 {
      tDemo1::show as toshow;
     //给tDemo1::show()起个别名: toshow
     tDemo::show insteadOf tDemo1;
     // show方法冲突时使用tDemo1类的show方法而不使用tDemo类的show方法
   }
}
class  Work
{
   use tDemo2;
}

echo (new  Work)->show();
echo (new  Work)->toshow();
image

5:trait和interface的组合

  • 通过trait实现interface接口的方法,然后实例化

    示例

interface iDemo //定义一个接口
{
  public  static  function index();
}
trait tDemo //定义一个trait
{
   public  static  function index()  //在tDemo中定义一个接口方法
   {
     return  '我是在trait中的!';
   }
}

class  Hello  implements iDemo //定义一个类实现iDemo
{
   use tDemo;  //类中应用trait
}

echo (new  Hello)->index();
//本实例定义一个接口,然后在trait中实现接口方法,然后实例化

示例图


image

相关文章

网友评论

      本文标题:Trait的五种应用场景

      本文链接:https://www.haomeiwen.com/subject/gjtvcltx.html