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. ElasticSearch(一)-- 简介

    ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用Java开发的,并作为Apach ...

  2. error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“0”不匹配值“2

    使用VS2013版本引用外部的lib进行编译时候提示: 错误 25 error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项:  值“0”不匹配值“2”(jrtpl ...

  3. Qt编写守护程序保证程序一直运行(开源)

    没有任何人敢保证自己写的程序没有任何BUG,尤其是在商业项目中,程序量越大,复杂度越高,出错的概率越大,尤其是现场环境千差万别,和当初本地电脑测试环境很可能不一样,有很多特殊情况没有考虑到,如果需要保 ...

  4. solus 系统 - 编译安裝 ibus-rime 中文输入法(附:小鹤双拼双形配置文件)

    編譯方法參見官網 - https://github.com/rime/home/wiki/RimeWithIBus 安装依赖:列出几个可能用到的命令 #安裝cmake gcc等开发工具 sudo eo ...

  5. Spring mvc 接口枚举类型数据格式化处理

    一.背景简述 首先,我们都知道枚举实例有两个默认属性,name 和 ordinal,可通过 name()和ordinal()方法分别获得.其中 name 为枚举字面量(如 MALE,FEMALE),o ...

  6. python爬虫+使用cookie登录豆瓣

    2017-10-09 19:06:22 版权声明:本文为博主原创文章,未经博主允许不得转载. 前言: 先获得cookie,然后自动登录豆瓣和新浪微博 系统环境: 64位win10系统,同时装pytho ...

  7. 泡泡一分钟:A Multi-Position Joint Particle Filtering Method for Vehicle Localization in Urban Area

    A Multi-Position Joint Particle Filtering Method for Vehicle Localization in Urban Area 城市车辆定位的多位置联合 ...

  8. 淘宝NPM镜像cnpm

    # 安装cnpm命令 npm install -g cnpm --registry=https://registry.npm.taobao.org2.cnpm install

  9. BZOJ 1002 - 轮状病毒 - [基尔霍夫矩阵(待补)+高精度]

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1002 Description 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生 ...

  10. bilibili的直播第三方IJKMediaFramework.framework下载打包使用教程

    参考和引用的地址: http://www.code4app.com/thread-8941-1-1.html http://blog.csdn.net/cccallen/article/details ...