共计 2350 个字符,预计需要花费 6 分钟才能阅读完成。
提到 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(); //1 | |
$b->test1(); //2 |
比照 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
以上内容心愿帮忙到大家,很多 PHPer 在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不晓得该从那里动手去晋升,对此我整顿了一些 PHP 高级、架构视频材料和大厂 PHP 面试 PDF| 收费获取能够关注公众号:PHP 开源社区