ホームページ  >  に質問  >  本文

php中trait的意义是什么呢?

看过了一些trait的介绍,也在框架中看到了。但是感觉trait做的事情,用interface是不是也能做呢?

个人感觉每个trait实现的功能都非常集中,也非常轻量,这个很赞,但是相对的有些class可能要同时用好几个trait,而且假如同时继承了类,实现了接口,并且其中包含覆盖,那理清这个类的关系感觉会很困难,这是我最困惑的地方,当然也可能是我技术还不够。

但是既然出了这个语法,肯定还是有他的道理的,所以就想问一下,项目中使用trait的意义是什么呢?

天蓬老师天蓬老师2770日前1236

全員に返信(12)返信します

  • 天蓬老师

    天蓬老师2017-04-10 18:09:08

    有不少目的,我相信其他的答案会从各个角度提及。

    我所知道的一个重要目的是:方便代码生成器的工作。

    如果一个类的部分代码是生成器产生的,部分代码是自己写的,那么我们肯定希望生成器产生的代码在trait里,我们自己写的代码引用这个trait。这样如果生成器需要重新运行,自写的代码就无需任何变化。

    这一点用继承也许也能做到,但PHP没有多继承。同时引用多个生成器产生的代码,只能依赖trait

    这一点你可以看一下 C# 的“部分类”(partial class)。在目的上是很相似的。

    返事
    0
  • 阿神

    阿神2017-04-10 18:09:08

    trait和interface恰好相反,interface关心的是接口,把实现丢给其他人,而trait完全不关心接口(约定),只提供实现。不那么准确地说的话,trait = abstract class - interface,提供了另一个维度的灵活性

    一个常见的应用场景是为接口提供“默认实现”,比如经典的\Psr\Log\LoggerInterface接口,有一堆方法(critical/emerg/info/debug)等等,但实际实现的时候,大家都会把这些方法都转发到log()方法里去,所以PSR提供了\Psr\Log\LoggerTrait,这样既保持了接口的完整(每个错误等级都有独立的方法),又方便了实现者

    返事
    0
  • 天蓬老师

    天蓬老师2017-04-10 18:09:08

    你可以这么理解
    1、trait 用来复用代码的
    2、解决了 php 不能多继承的问题(多继承也会产生问题,这里不展开)
    3、使用 trait的类,跟 trait 本身是可以没有任何关系的

    .......

    trait 里面定义了实现
    interface 只是声明
    这两个还是有区别的

    ......

    返事
    0
  • 天蓬老师

    天蓬老师2017-04-10 18:09:08

    PHPJava等大多数面向对象的语言一样是单继承,既一个类只能继承于一个父类。虽然单继承是公认使代码清晰准确的方式,但有时候多继承也有自己的优势。trait的出现就是一种解决需要多继承场景的方式。多继承的好处就是让一个类继承多个父类的功能,虽然这违反了类单一职责原则,但是在某些场合下,一些小功能使用多继承是最合适不过的。比如Laravel中定义了一个宏trait,只是很简单的让类实现一些类似C宏定义的方法,因为这其中含有一些实体方法和属性,所以通过interface定义是不能实现的,而需要使用这个功能的类又有可能已经继承于其他类,所以通过abstract class定义也是不能实现的,所以这种场合下trait就能体现它的优势了。

    返事
    0
  • 巴扎黑

    巴扎黑2017-04-10 18:09:08

    这篇博客中有讲到哦,可以看看
    http://overtrue.me/articles/2016/04/about-php-trait.html

    返事
    0
  • 天蓬老师

    天蓬老师2017-04-10 18:09:08

    在解决多继承的代码中用的较多

    返事
    0
  • 怪我咯

    怪我咯2017-04-10 18:09:08

    减少复制粘贴造成的维护不便问题

    返事
    0
  • 高洛峰

    高洛峰2017-04-10 18:09:08

    通俗一点,就是能把重复的方法拆分到一个文件,通过 use 引入以达到代码复用的目的

    返事
    0
  • 阿神

    阿神2017-04-10 18:09:08

    看了一下trait的定义,并测试了一下。感觉是把设计模式里面的适配器模型做到语言层面了。
    多继承的语言没用过,不敢做评论。就看到的几个实例,都可以使用适配器+接口实现,只是实现起来比较绕,没有trait这么清晰。

    返事
    0
  • 黄舟

    黄舟2017-04-10 18:09:08

    个人理解:在一个类中使用Trait,就相当于这个类也有了Trait中定义的属性和方法。Traits的使用场景是如果多个类都要用到同样的属性或者方法,这个时候使用Traits可以方便的给类增加这些属性或方法,而不用每个类都去继承一个类,如果说继承类是竖向扩展一个类,那么Traits是横向扩展一个类,从而实现代码复用。

    Laravel中triat的使用:
    http://blog.tanteng.me/2015/12/laravel-trait/

    返事
    0
  • キャンセル返事