前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >萧峰与郭靖教你学会PHP的Trait

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

作者头像
章鱼喵
发布2018-06-27 15:17:13
4301
发布2018-06-27 15:17:13
举报
文章被收录于专栏:codingcoding

自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();

结果:

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

源码下载

源码仓库链接

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.07.22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • trait的使用场景
  • 方法/属性的重写
  • 组合多个trait
  • trait方法的访问控制
  • Trait组合
  • 源码下载
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档