萧峰与郭靖教你学会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 条评论
登录 后参与评论

相关文章

来自专栏别先生

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

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

66380
来自专栏源码之家

word如何自动分割成多个文档

47250
来自专栏黄Java的地盘

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

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

10110
来自专栏SeanCheney的专栏

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

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

60860
来自专栏老码农专栏

原 荐 OSGL 工具库 - Java 字串

20340
来自专栏跟着阿笨一起玩NET

C# Eval在aspx页面中的用法及作用

31920
来自专栏Celebi的专栏

C/C++ 学习笔记六(文件系统、预处理)

工作中经常使用到C/C++,为对C有个比较深刻的了解,重新拾起学习C的任务。在看书的同时,记录下思考的过程,也记录下重要的知识点。

14300
来自专栏java学习

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

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

28070
来自专栏编程坑太多

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

19730
来自专栏jeremy的技术点滴

JVM的Finalization Delay引起的OOM

43280

扫码关注云+社区

领取腾讯云代金券