首页 > php中trait的意义是什么呢?

php中trait的意义是什么呢?

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

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

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


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


我们通常的类继承(extend) 会继承整个类,如果要是继承多了,就会造成耦合度非常高,阅读起来非常麻烦,重构也非常困难,Trait的出现就恰巧解决了这一点,Trait就相当于把几个方法注入到了类中,从而不必关心继承,让代码更加灵活


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

.......

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

......


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

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


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


其实
trait
就是
解决多继承的问题。


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


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

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

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

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

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


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

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


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


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


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

【热门文章】
【热门文章】