PHP之Trait特性
admin
2023-06-13 12:02:56
0
自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait。
  • Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method。Trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。
  • Trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个 Class 之间不需要继承。
logger = $logger;
    }

    /**
     * 读取日志
     * @param string $message
     * @param int $level
     */
    public function getLog(string $message, int $level)
    {
        $this->logger->log($message, $level);
    }

    public function test()
    {
        echo 'trait test' . PHP_EOL;
    }
}

//基类
class Base
{
    public static $className = 'Base';

    public function test()
    {
        echo static::getClassName() . ' test' . PHP_EOL;
    }

    //获取类名称
    public static function getClassName(): string
    {
        //return self::$className;
        return static::$className;//static延时静态绑定
    }
}

class Foo extends Base
{
    public static $className = 'Foo';
    use Loggable;
}

$foo = new Foo;
$foo->setLogger(new Logger);
$foo->getLog('trait works', 1);//打印日志信息

$foo->test(); //trait test
  • 分析这里 $foo->test()
    • Foo类中使用use Loggable来扩展Foo类增加日志功能;
    • Trait Loggable类中含有test()方法;
    • Foo类继承Base类,其中Base类中含有test();
    • 那么问题来了:$foo->test()到底调用的是继承自父类test(),还是Trait类中的test()?

Trait优先级
当前类的函数会覆盖 trait 的同名函数,trait 会覆盖父类的同名函数( use trait 相当于当前类直接覆写了父类的同名函数)

因此,$foo->test()调用的是Trait类中的方法



使用多个Trait及冲突的解决
Trait Alibaba
{
    public function getCEO(): string
    {
        return '阿里巴巴CEO:马云' . PHP_EOL;
    }

    public function getAddress(): string
    {
        return '阿里巴巴总部位于杭州' . PHP_EOL;
    }
}

Trait Tencent
{
    public function getCEO(): string
    {
        return '腾讯CEO:马化腾' . PHP_EOL;
    }

    public function getAddress(): string
    {
        return '腾讯总部位于深圳' . PHP_EOL;
    }
}

class TopBoss
{
    use Alibaba, Tencent;
}

$MaBoss = new TopBoss();

echo $MaBoss->getCEO();
echo $MaBoss->getAddress();

解决方案

  • 使用 insteadof(取代) 操作符来明确指定使用冲突方法中的哪一个
  • as 操作符可以 为某个方法引入别名。 注意,as 操作符不会对方法进行重命名,也不会影响其方法。

最终代码:

class TopBoss
{
    use Alibaba, Tencent {
        Tencent::getCEO insteadof Alibaba;//指定冲突时,使用谁
        Tencent::getAddress insteadof Alibaba;
        Alibaba::getAddress as getA;//取别名,可以通过别名调用
        Alibaba::getCEO as getC;
    }
}

$MaBoss = new TopBoss();

echo $MaBoss->getCEO();//腾讯CEO:马化腾
echo $MaBoss->getAddress();//腾讯总部位于深圳

echo $superBoss->getC();//阿里巴巴CEO:马云
echo $superBoss->getA();//阿里巴巴总部位于杭州

Laravel中的代码示例

macroCall($method, $parameters);
        }
                ...
    }

相关内容

热门资讯

鲁比奥紧急安抚,但“若美国对华... 【文/观察者网 王一】当地时间5月26日,美国国务卿鲁比奥将结束为期4天的访印行程。从与印度总理莫迪...
打响“河南服务”品牌丨用江湖情... 2025年,开封万岁山武侠城全年综合营收达12.7亿元,接待游客2452.2万人次,营收3年间增长1...
凡星闪耀丨一个人的光影山路 —... “放电影去?”“对,今天去王家辿。”5月13日傍晚,李全民开着汽油三轮车,刚拐进鹤壁市鹤山区姬家山乡...
今年我国养老机器人市场规模将破... 今天(26日),中国软件评测中心发布了《智能养老服务机器人产业演进与未来趋势研究》报告。报告显示,我...
中国之城|河南安阳:如切如削的... 新华社郑州5月25日电 题:河南安阳:如切如削的山前之城当你站在河南安阳的林州太行阁前,会瞬间秒懂“...
中信建投:海外AI行业核心投资... 人民财讯5月26日电,中信建投证券研报称,海外AI行业核心投资逻辑呈现两条主线:在硬件与基础设施端,...
中华人民共和国和塞尔维亚共和国... 新华社北京5月25日电中华人民共和国和塞尔维亚共和国关于持续推进构建新时代中塞命运共同体的联合声明应...
原创 “... 长沙晚报掌上长沙5月25日讯(全媒体记者 周斌 通讯员 熊奇欢 周秋燕)24日,搭载神舟二十三号载人...
大模型公司门口,挤满了送钱的投... 文 | 白鲸实验室 今年大模型公司最大的变数之一,是DeepSeek也开始下场融资。这意味着,即使...
安克创新:具身智能相关研发正按... 上证报中国证券网讯(记者 夏子航)在5月24日披露的投资者关系活动记录表中,安克创新表示,公司在具身...