萧峰与郭靖教你学会PHP的Trait

自PHP5.4之前,PHP面向对象需要复用代码的方式是使用类的继承。但PHP只支持单继承,在应对较复杂的业务逻辑中,单继承就显得捉襟见肘了。

trait的使用场景

如以下应用场景:

class Person {
    public function eat() {
        echo "我是人,我能吃饭<br />";
    }
}

class GuoJing extends Person {
    public function kungfu() {
        echo "降龙十八掌!<br />";
    }
}

class XiaoFeng extends Person {
    public function kungfu() {
        echo "降龙十八掌!<br />";
    }
}

萧峰

Guojing 类 与 XiaoFeng 类都继承于Person,都有共同的 Kungfu 方法,显然,我们不能将这个 Kungfu 方法写到 Person 类,不然随便一个路人甲继承了 Person 类,就拥有了 Kungfu 技能。

用Trait就能解决此问题:

<?php
trait Tool {
    public function kungfu() {
        echo "降龙十八掌!<br />";
    }
}

class Person {
    public function eat() {
        echo "我是人,我能吃饭<br />";
    }
}

class GuoJing extends Person {
    use Tool;
}

class XiaoFeng extends Person {
    use Tool;
}

$guojing = new GuoJing();
$xiaofeng = new XiaoFeng();

$guojing->kungfu();
$xiaofeng->kungfu();

结果如下:

降龙十八掌!
降龙十八掌!

方法/属性的重写

如果Trait类、基类和本类中的方法或属性同名,最终会以哪个为准?

<?php
trait Tool {
    public function kungfu() {
        echo "降龙十八掌!<br />";
    }
}

class Person {
    public function eat() {
        echo "我是人,我能吃饭<br />";
    }

    public function kungfu() {
        echo "不是每个人都会功夫<br />";
    }
}

class GuoJing extends Person {
    use Tool;
    public function kungfu() {
        echo "除了降龙十八掌,我还懂九阴真经!<br />";
    }
}

class XiaoFeng extends Person {
    use Tool;
}

$guojing = new GuoJing();
$guojing->kungfu();

结果:

除了降龙十八掌,我还懂九阴真经!

注释本类的 kungfu 方法,得出的结果是:

降龙十八掌!

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

组合多个trait

多个trait有同名的方法/属性时,会报错:

<?php
trait Tool {
    public function kungfu() {
        echo "降龙十八掌!<br />";
    }
}

trait Skill {
    public function kungfu() {
        echo "浑厚的内力修为<br />";
    }
}

class GuoJing {
    use Tool, Skill;
}

$guojing = new GuoJing();
$guojing->kungfu();
Fatal error: Trait method kungfu has not been applied, because there are collisions with other trait methods on GuoJing 

解决方式:使用insteadof和as来解决冲突

  • insteadof: 使用某个方法替代另一个
  • as: 给方法取别名
<?php
trait Tool {
    public function kungfu() {
        echo "降龙十八掌!<br />";
    }
}

trait Skill {
    public function kungfu() {
        echo "浑厚的内力修为<br />";
    }
}

class XiaoFeng {
    use Tool, Skill {
        Skill::kungfu insteadof Tool;
        Skill::kungfu as ability;
    }
}

$xiaofeng = new XiaoFeng();
$xiaofeng->ability();
浑厚的内力修为

trait方法的访问控制

as关键词可以修改方法的访问控制

<?php
trait Tool {
    public function kungfu() {
        echo "降龙十八掌!<br />";
    }
}

class XiaoFeng {
    use Tool {
        Tool::kungfu as protected ability; // 修改方法的访问控制并起别名
    }
}

$xiaofeng = new XiaoFeng();
$xiaofeng->ability();

报错:

Fatal error: Uncaught Error: Call to protected method XiaoFeng::ability() from context

Trait组合

Trait也能组合Trait,同时,Trait中支持抽象方法、静态属性、静态方法。

<?php
trait Tool {
    public function kungfu() {
        echo "降龙十八掌!<br />";
    }
}

trait Feature{
    use Tool;
    abstract public function dream();
    public static function character() {
        echo "磊落豪雄 <br />";
    }
}

class XiaoFeng {
    use Feature;
    public function dream() {
        echo "弄清楚:我是谁? <br />";
    }
}

$xiaofeng = new XiaoFeng();
$xiaofeng->kungfu();
XiaoFeng::character();
$xiaofeng->dream();

结果:

降龙十八掌!
磊落豪雄 
弄清楚:我是谁? 

源码下载

源码仓库链接

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏数据结构与算法

BZOJ1269: [AHOI2006]文本编辑器editor

Descriptio 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器。你能帮助他吗? 为了明确任务目标,可可对“文本编辑器...

2687
来自专栏TechBox

一份走心的iOS开发规范前言约定(一)命名规范(二)编码规范2.14 内存管理规范本文参考文章其他有价值的文章

4808
来自专栏java学习

Java每日一练(2017/6/8)

Java基础 | 数据库 | Android | 学习视频 | 学习资料下载 课前导读 ●回复"每日一练"获取以前的题目! ●答案公布时间:为每期发布题目的第二...

2667
来自专栏编程坑太多

java:工作中常用到的工具类

1283
来自专栏SeanCheney的专栏

《利用Python进行数据分析·第2版》第6章 数据加载、存储与文件格式6.1 读写文本格式的数据6.2 二进制数据格式6.3 Web APIs交互6.4 数据库交互6.5 总结

访问数据是使用本书所介绍的这些工具的第一步。我会着重介绍pandas的数据输入与输出,虽然别的库中也有不少以此为目的的工具。 输入输出通常可以划分为几个大类:读...

5266
来自专栏NetCore

[收藏]几个常用的用正则表达式验证字符串的函数

<!-- name,phone,age,money checked--> <script language=javascript runat=server> ...

2008
来自专栏jeremy的技术点滴

JVM的Finalization Delay引起的OOM

3748
来自专栏iOS开发

iOS开发之 Method Swizzling 深入浅出

如果产品经理突然说:"在所有页面添加统计功能,也就是用户进入这个页面就统计一次"。我们会想到下面的一些方法:

4687
来自专栏黄Java的地盘

[翻译]WebSocket协议第二章——Conformance Requirements

本文为WebSocket协议的第二章,本文翻译的主要内容为WebSocket协议中相关术语的介绍。

791
来自专栏别先生

c3p0和QueryRunner的结合使用,让开发更加简便

1:DBUtils中的QueryRunner的使用:   1.1:QueryRunner中提供了对SQL语句操作的api;   1.2:主要有三个方法:    ...

5698

扫码关注云+社区