PHP trait 及其应用场景、trait 与接口,抽象类之间的区别
trait
可以使多个无关的类共用同一种方法或属性trait
无法实例化,在类中使用use
关键字引用
应用场景 1:代码复用
<?php
trait tSum{
public function sum($a, $b){
return $a + $b;
}
}
class countNum{
use tSum;
}
class totalPrice{
use tSum;
}
echo (new countNum)->sum(10, 20),'<br>';
echo (new totalPrice)->sum(3, 20),'<br>';
应用场景 2:同名方法在 trait 与父类与子类的关系
- 同名成员在 trait 中优先级高于子类的父类
- 同名成员在子类中优先级高于 trait
- 同名成员在子类中优先级高于父类
<?php
trait tRet{
public static function ret(){
return 'trait';
}
}
class cFRet{
use tRet;
public static function ret(){
return '父类';
}
}
class cSRet extends cFRet{
use tRet;
public static function ret(){
return '子类';
}
}
//此时浏览器上输出子类 可以看出 子类优先级要高于父类与`trait`
//当在子类中注释掉成员方法之后 浏览器上输出trait 可以看出 trait的优先级要高于父类
//当在子类中注释掉use trait之后 浏览器上输出子类 可以看出 类优先级要高于父类
echo cSRet::ret(),'<br>';
- 当子类中注释trait引用时
- 显示子类 说明子类比父类优先级高
- 当子类中注释同名方法时
- 显示
trait
说明trait
优先级比父类高
- 当子类中同时有
trait
与父类的同名方法时 - 只显示子类 说明子类优先级最高
应用场景 3:实现功能扩展
- 在 trait 中设计的成员方法可以被类引用
- 一个类中可以使用多个 trait 以扩展其中的方法
<?php
trait tRet1{
public static function ret1(){
return '你好';
}
}
trait tRet2{
public static function ret2(){
return 'php';
}
}
trait tRet{ //组合两个trait
use tRet1, tRet2;
}
class cRet{
use tRet; //use tRet1, tRet2;
}
echo cRet::ret1().':'.cRet::ret2();
应用场景 4:trait 中同名成员方法的处理
- 使用关键字
as
给其中一个同名方法起个别名 - 使用关键字
insteadOf
来明确指定使用冲突方法中的哪一个
<?php
trait hello{
public function hw(){
return 'hello';
}
}
trait world{
public function hw(){
return 'world';
}
}
class hello_wrold{
use hello, world{
hello::hw as hello;
world::hw insteadOf hello;
}
}
echo (new hello_wrold)->hw(),'<br>';
//使用别名访问
echo (new hello_wrold)->hello();
- 当未使用
as
与insteadOf
时产生冲突
冲突处理之后
应用场景 5:trait 与接口
使用 trait 实现接口中的方法
<?php
//声明一个接口定义helloWorld方法
interface iHelloWorld{
public function helloWorld();
}
//声明一个triat 实现helloWorld方法
trait tHelloWorld{
public function helloWorld(){
return 'Hello World';
}
}
//声明一个工作类 实现接口 使用trait
class cHelloWorld implements iHelloWorld{
use tHelloWorld;
}
echo (new cHelloWorld)->helloWorld();
trait 与接口,抽象类之间的区别
trait
是通过代码复用来实现具体功能扩展interface
是通过代码声明一些特定功能,没有具体的实现内容- 抽象类是对类对象的抽象,不能进行实例化,实际上是某一类的抽象集合
- 一个实现类可以使用多个
trait
或者多个interface
,但只能继承一个抽象类
<?php
//声明一个接口 特定行为:握手
interface iAction{
public function shakeHands();
}
//声明一个trait 实现握手行为
trait tShakeHands{
public function shakeHands(){
return true;
}
}
//声明一个抽象类 狗类:吠、摇尾巴
abstract class aDogs{
abstract public function bark();
abstract public function wagTail();
}
//实现类 实现一只狗的基本属性行为
class Dog extends aDogs implements iAction{
use tShakeHands;
public function bark(){
return true;
}
public function wagTail(){
return true;
}
}
//输出
$myDog = new Dog();
echo 'my dog '.($myDog->bark()?'can':'cannot').' bark<br>';
echo 'my dog '.($myDog->wagTail()?'can':'cannot').' wagging its tail<br>';
echo 'my dog '.($myDog->shakeHands()?'can':'cannot').' shake hands';