https://juejin.im/entry/5927ec4544d904006413f61d

提到 php 的代码复用,我们可能第一时间会想到继承,但是这种单继承语言一旦派生的子类过多,那么会产生一系列的问题,比如依赖父类、耦合性太大、破坏了类的封装性。那么有没有更好的方法来实现代码复用呢?

自 PHP 5.4.0 起,PHP 实现了另外一种代码复用的一个方法,称为 traits。

Traits 是一种为类似 PHP 的单继承语言而准备的代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用方法集。Traits 和类组合的语义是定义了一种方式来减少复杂性,避免传统多继承和混入类(Mixin)相关的典型问题。

基础使用方法

Traits 的使用非常简单,只需要在类中使用 use 关键字即可。

trait A {
public function test() {
echo 'trait A::test()';
}
} class b {
use A;
}
$b=new b();
$b->test();

优先级

简单来说 Trait 优先级大于父类方法,但是小于当前类方法。

trait A {
public function test() {
echo 'trait A::test()';
}
public function test1() {
echo 'trait A::test1()';
}
} class base{
public function test(){
echo 'base::test()';
}
public function test1(){
echo 'base::test1()';
}
}
class b extends base{
use A;
public function test(){
echo 'b::test()';
}
}
$b=new b();
$b->test();//b::test()
$b->test1();//trait A::test1()

Trait冲突问题

在使用多个 Trait 时,如果其中存在相同的方法名称,那么就会产生冲突。使用 insteadof 和 as 可以解决方法名称冲突问题

insteadof可以声明使用两个相同方法名称中的具体某个方法。

trait A {
public function test() {
echo 'trait A::test()';
}
}
trait B {
public function test() {
echo 'trait B::test()';
}
}
class c{
use A,B{
A::test insteadof B;//使用 insteadof 明确使用哪个方法
B::test as testB;//使用 as 修改另外一个方法名称,必须在使用 insteadof 解决冲突后使用
}
}
$c=new c();
$c->test();//trait A::test()
$c->testB();//trait B::test()

方法访问控制

使用 as 关键字我们可以对 trait 方法的访问权限进行修改

trait A {
public function test() {
echo 'trait A::test()';
}
private function test1(){
echo 'trait A::test1()';
}
}
class b{
use A{
test as protected;
test1 as public test2;//更改权限时还可以修改名称
}
}
$b=new b();
$b->test();//Fatal error: Call to protected method b::test()
$b->test2();//trait A::test1()

Trait嵌套使用

trait A {
public function test1() {
echo 'test1';
}
} trait B {
public function test2() {
echo 'test2';
}
} trait C {
use A,B;
} class D {
use C;
} $d = new D();
$d->test2(); //test2

变量、属性、方法定义

Trait可定义属性,但类中不能定义同样名称属性

trait A {
public $test1;
} class B {
use A;
public $test;
public $test1;//Strict Standards: B and A define the same property ($test1) in the composition of B...
}

Trait支持抽象方法、支持静态方法、不可以直接定义静态变量,但静态变量可被trait方法引用。

trait A {
public function test1() {
static $a = 0;
$a++;
echo $a;
} abstract public function test2(); //可定义抽象方法
} class B {
use A;
public function test2() { }
} $b = new B();
$b->test1(); //
$b->test1(); //

对比javascript

这种 trait use 的使用方法大概和 javascript 中的 call 有点相似,都是把一个另外一个对象挂载到当前对象的执行环境当中。当然 javascript 是基于原型的语言。两者也没有可比性。仅仅是使用方法相差无几,有助于理解。

function a() {
this.name="a";
this.getName=function(){
console.log(this.name);
}
} function b(){
this.name="b";
a.call(this);
}
var b = new b();
b.getName();//a

因为 javascript 中的变量环境是基于函数的,所以会输出a

php 代码复用机制的更多相关文章

  1. PHP代码的多继承 -》 PHP代码复用新的姿势 trait

    本文参考:  http://php.net/language.oop5.traits 一.什么是trait 从PHP 5.4.0 开始 PHP 实现了一种新的代码复用方式 trait. 二.trait ...

  2. PHP 实现了一种代码复用的方法,称为 trait

    自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait. Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制.Trait 为了减少单继承语言的限制,使开发人员能 ...

  3. Atitit 代码复用的理解attilax总结

    Atitit 代码复用的理解attilax总结 1.1. 继承1 1.1.1. 模式1:原型继承1 1.1.2. 模式2:复制所有属性进行继承 拷贝继承1 1.1.3. 模式3:混合(mix-in)1 ...

  4. Android学习笔记之ListView复用机制

    PS:满打满算,差不多三个月没写博客了...前一阵忙的不可开交...总算是可以抽出时间研究研究其他事情了... 学习内容: 1.ListView的复用机制 2.ViewHolder的概念 1.List ...

  5. cell 的复用机制

    一个问题引发的血案,以下是本侦探的探案过程的一部分:以下全部都是转载自别人的博客:http://blog.sina.com.cn/s/blog_9c3c519b01016aqu.html 转自:htt ...

  6. javascript代码复用模式

    代码复用有一个著名的原则,是GoF提出的:优先使用对象组合,而不是类继承.在javascript中,并没有类的概念,所以代码的复用,也并不局限于类式继承.javascript中创建对象的方法很多,有构 ...

  7. Android AdapterView View的复用机制 分析

    对于ListView.GridView相信大家都不陌生,重写个BaseView,实现对于的几个方法,然后就完毕了我们的界面展示.而且在大部分情况下,我们载入特别多的Item也不会发生OOM,大家也都明 ...

  8. 基于场景解析RecyclerView的回收复用机制原理

    最近在研究 RecyclerView 的回收复用机制,顺便记录一下.我们知道,RecyclerView 在 layout 子 View 时,都通过回收复用机制来管理.网上关于回收复用机制的分析讲解的文 ...

  9. cell的复用机制

    以下全部都是转载自别人的博客:http://blog.sina.com.cn/s/blog_9c3c519b01016aqu.html 转自:http://www.2cto.com/kf/201207 ...

随机推荐

  1. windows上测试磁盘io性能

    一.问题由来 前两天搭建一套演示环境,同样的java war包,放在我们这边服务器好好的,放在那边就运行缓慢. 后来把日志改成异步之后就好了. 后边找了个程序测了下io性能,竟然差了7,8倍. 二.软 ...

  2. web项目加载图片资源

    在web项目中,用户会上传图片,这些图片应该存在服务器硬盘上,而不是存在数据库或者应用程序路径下,在数据库存入文件的路径. 这是一个比较重要的问题,也是开发过程中也解决的问题.当然,我可以跳过,但是成 ...

  3. Selenium模拟浏览器抓取淘宝美食信息

    前言: 无意中在网上发现了静觅大神(崔老师),又无意中发现自己硬盘里有静觅大神录制的视频,于是乎看了其中一个,可以说是非常牛逼了,让我这个用urllib,requests用了那么久的小白,体会到sel ...

  4. Codeforces 1114E - Arithmetic Progression - [二分+随机数]

    题目链接:http://codeforces.com/problemset/problem/1114/E 题意: 交互题,有一个 $n$ 个整数的打乱顺序后的等差数列 $a[1 \sim n]$,保证 ...

  5. C和C指针小记(四)-浮点类型

    1.浮点型 浮点数家族包括:float,double,long double. ASCII标准规定:long double 至少和 double 一样长,而 double 至少和float 一样长.同 ...

  6. iOS中UITableView的一些问题思考

    UITableview的数据源为什么是代理,而不是引用? 我的理解,一般情况下控制器会引用tableView, 数据源和代理方法都是tableView的一个若引用,出了“tableView.datas ...

  7. hung_task_timeout_secs和blocked for more than 120 seconds的解决方法

    Linux系统出现hung_task_timeout_secs和blocked for more than 120 seconds的解决方法 Linux系统出现系统没有响应. 在/var/log/me ...

  8. iphone及ipad屏幕尺寸参考

    初代iPhone 2007年,初代iPhone发布,屏幕的宽高是 320 x 480 像素.下文也是按照宽度,高度的顺序排列.这个分辨率一直到iPhone 3GS也保持不变.那时编写iOS的App(应 ...

  9. 转:手把手教你如何玩转Solr(包含项目实战)

    原文地址:手把手教你如何玩转Solr(包含项目实战) 参考原文

  10. LeetCode 937 Reorder Log Files 解题报告

    题目要求 You have an array of logs.  Each log is a space delimited string of words. For each log, the fi ...