首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >只知道PHP是单继承语言,你了解Trait吗?

只知道PHP是单继承语言,你了解Trait吗?

作者头像
切图仔
发布于 2022-09-08 19:02:14
发布于 2022-09-08 19:02:14
6750
举报
文章被收录于专栏:生如夏花绚烂生如夏花绚烂

在学习laravel的时候总是看到代码中使用了trait,下面结合网上的资料谈谈我的理解加深印象

Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method。Trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。

说简单一点就是php是单继承语言,一个类只能继承一个基类,但如果你还想这个类继承其他类的属性或方法,就可以通过trait解决。

定义格式

代码语言:javascript
复制
trait Name{
   public $arr;
   public function test(){};
   ....
}

几乎和类的定义方式一样,但trait不是类因此trait不能实例化

调用格式

代码语言:javascript
复制
class ClassName {
    use traitName;
}

如下实例

代码语言:javascript
复制
<?php

trait Person{
    public function walk(){
        echo "person----walk";
    }
}

class Animal {
    public function eat(){
        echo "animal----eat";
    }
}

class Dog extends Animal{
    use Person;
    public function wang(){
        echo "wangwangwang";
    }
}

$dog1 = new Dog();
$dog1->eat();//animal----eat
$dog1->wang();//wangwangwang
$dog1->walk();//person----walk

Dog继承了Animal中的方法同时还可以调用trait Person中的方法

优先级

测试trait与基类本类方法重名

代码语言:javascript
复制
<?php
trait Person{
    public function walk(){
        echo "person----walk";
    }
    public function test(){
        echo "person----test";
    }
}

class Animal {
    public function eat(){
        echo "animal----eat";
    }
    public function walk(){
        echo "animal----walk";
    }
}

class Dog extends Animal{
    use Person;
    public function wang(){
        echo "wangwangwang";
    }
    public function test(){
        echo "Dog----test";
    }
}

$dog1 = new Dog();
$dog1->test();//Dog----test
echo "<br />";
$dog1->walk();//person----walk

当trait与基类的方法重名时trait方法会覆盖基类中的方法,当trait中的方法与本来重名时本类中的方法会覆盖trait中的方法即 本类>trait>基类

在trait中定义了属性,基类或本类就不能使用同名属性,反之报错但是在PHP 7.0.0之后只要属性的初始值以及可见性一致的时候会正常运行

代码语言:javascript
复制
<?php
trait Wuman{
    public $name = 12;
    public function sky(){
        echo "wuman----sky";
    }
}
class Dog {
    // public $name = 'animal';
    use Wuman;
    public $name = 12;
    protected $name = 12;//可见性不一样报错
    public $name = 13;//初始值不一样报错
    public function wang(){
        echo "wangwangwang";
    }
    public function test(){
        echo "Dog----test";
    }
}

$dog1 = new Dog();
$dog1->test();//Dog----test

多个trait

类里面可以使用多个trait通过逗号分隔即可

代码语言:javascript
复制
<?php
trait Human{
    public function show(){
        echo "human----show";
    }
}
trait Person{
    public $name = 'human';
    public function walk(){
        echo "person----walk";
    }
    public function test(){
        echo "person----test";
    }
}

class Animal {

    public function eat(){
        echo "animal----eat";
    }
    public function walk(){
        echo "animal----walk";
    }
}

class Dog extends Animal{
    // public $name = 'animal';
    use Person,Human;

    public function wang(){
        echo "wangwangwang";
    }
    public function test(){
        echo "Dog----test";
    }
}

$dog1 = new Dog();
$dog1->test();//Dog----test
echo "<br />";
$dog1->walk();//person----walk

$dog1->show();//walkhuman----show

但是多个trait难免会遇到方法重名的问题,这里通过insteadof替换 和 as取别名的方式解决

代码语言:javascript
复制
<?php
trait Human{
    public function show(){
        echo "human----show";
    }
}
trait Person{
    public $name = 'human';
    public function walk(){
        echo "person----walk";
    }
    public function test(){
        echo "person----test";
    }
    public function show(){
        echo "Person---show";
    }
}


class Dog {
    // public $name = 'animal';
    use Person,Human{
        Person::show insteadof Human;
    }
    public function wang(){
        echo "wangwangwang";
    }
    public function test(){
        echo "Dog----test";
    }
}
$dog1 = new Dog();
$dog1->test();//Dog----test
echo "<br />";
$dog1->walk();//person----walk
echo "<br />";
$dog1->show();//Person----show

上面代码通过insteadof使Human与Person的同名方法优先执行Person所以程序输出person----show,此时如果还想使用Human中的show方法可通过as取别名的方式

代码语言:javascript
复制
<?php
trait Human{
    public function show(){
        echo "human----show";
    }
}
trait Person{
    public $name = 'human';
    public function walk(){
        echo "person----walk";
    }
    public function test(){
        echo "person----test";
    }
    public function show(){
        echo "Person---show";
    }
}


class Dog {
    // public $name = 'animal';
    use Person,Human{
        Person::show insteadof Human;
        Human::show as huShow;

    }

    public function wang(){
        echo "wangwangwang";
    }
    public function test(){
        echo "Dog----test";
    }
}

$dog1 = new Dog();
$dog1->test();//Dog----test
echo "<br />";
$dog1->walk();//person----walk
echo "<br />";
$dog1->show();//Person----show
echo "<br />";
$dog1->huShow();//human----show

使用 as 语法还可以用来调整方法的访问控制

代码语言:javascript
复制
use Person,Human{
    Person::show insteadof Human;
    Human::show as private huShow;
}

trait中使用trait

代码语言:javascript
复制
<?php
trait Wuman{
    public function sky(){
        echo "wuman----sky";
    }
}
trait Human{
    use Wuman;
    public function show(){
        echo "human----show";
    }
}
trait Person{
    public $name = 'human';
    public function walk(){
        echo "person----walk";
    }
    public function test(){
        echo "person----test";
    }
    public function show(){
        echo "Person---show";
    }
}
class Dog {
    // public $name = 'animal';
    use Person,Human{
        Person::show insteadof Human;
        Human::show as  huShow;

    }

    public function wang(){
        echo "wangwangwang";
    }
    public function test(){
        echo "Dog----test";
    }
}

$dog1 = new Dog();
$dog1->test();//Dog----test
echo "<br />";
$dog1->walk();//person----walk
echo "<br />";
$dog1->show();//Person----show
echo "<br />";
$dog1->huShow();//human----show
echo "<br />";
$dog1->sky();//wuman----sky

trait中的抽象类

trait中可以使用抽象类对类施加强制要求

代码语言:javascript
复制
<?php
trait Wuman{
    public function sky(){
        echo "wuman----sky";
    }
    abstract public function test();
}
class Dog {
    // public $name = 'animal';
    use Wuman;

    public function wang(){
        echo "wangwangwang";
    }
    public function test(){
        echo "Dog----test";
    }
}

$dog1 = new Dog();
$dog1->test();//Dog----test
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-04-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档