文章目录
前言
本文就介绍了PHP代码复用trait的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
一、代码复用trait
- trait实现了PHP代码复用的一种方法。
- 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method。
- Trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。
- 无法通过 trait 自身来实例化。
- 应用的几个 Class 之间不需要继承。
trait MyClass{ //和Class相似
function SaySomeThing() {echo "Hello<br>";}
function SaySomeThing1() {echo "你好<br>";}
}
class MyClass1{
use MyClass;
}
$foo = new MyClass1(); //注意:trait无法自身实例化,不能new MyClass();
$foo->SaySomeThing();
- 优先级:从基类继承的成员会被 trait 插入的成员所覆盖。优先顺序是来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法。
class BaseClass{ //基类有一个SaySomeThing和SaySomeThing1方法
function SaySomeThing() {
echo "BaseClass-SaySomeThing<br>";
}
function SaySomeThing1() {
echo "BaseClass-SaySomeThing1<br>";
}
}
trait MyClass{ //trail中有一个和基类一样的方法SaySomeThing
function SaySomeThing() {
parent::SaySomeThing1();
echo "Trait-SaySomeThing<br>";
}
}
class MyClass1 extends BaseClass{ //子类继承基类
use MyClass; //子类使用trait
}
$foo = new MyClass1();
$foo->SaySomeThing(); //会输出BaseClass-SaySomeThing1和Trait-SaySomeThing
//如果子类MyClass1中有SaySomeThing(),优先执行MyClass1的SaySomeThing()
//如果子类MyClass1中没有SaySomeThing(),优先执行trait中的SaySomeThing()
//如果子类MyClass1和trait中都没有SaySomeThing(),会执行父类MyClass中的SaySomeThing()
- 在 use 声明列出多个 trait,可用逗号分隔。
- 如果两个 trait 都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。
- 为了解决多个 trait 在同一个类中的命名冲突,需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个。
- as 操作符可以 为某个方法引入别名。
trait MyClass1{
function SaySomeThing1(){
echo "MyClass1-SaySomeThing1()<br>";
}
function SaySomeThing2(){
echo "MyClass1-SaySomeThing2()<br>";
}
}
trait MyClass2{
function SaySomeThing1(){
echo "MyClass2-SaySomeThing1()<br>";
}
function SaySomeThing2(){
echo "MyClass2-SaySomeThing2()<br>";
}
}
class MyClass{
// use MyClass1,MyClass2; //这时如果直接像这样use会报一个致命错误,因为两个trait都含有相同的方法名
use MyClass1,MyClass2{
MyClass1::SaySomeThing1 insteadof MyClass2; //使用MyClass1中的SaySomeThing1代替MyClass2
MyClass2::SaySomeThing2 insteadof MyClass1; //使用MyClass2中的SaySomeThing2代替MyClass1
MyClass2::SaySomeThing2 as SaySomeThing; //给MyClass2中的SaySomeThing2取别名SaySomeThing
}
}
$foo = new MyClass();
$foo->SaySomeThing(); //输出MyClass2-SaySomeThing2()
$foo->SaySomeThing1(); //输出MyClass1-SaySomeThing1()
$foo->SaySomeThing2(); //输出MyClass2-SaySomeThing2()
- 通过as还可以修改方法的访问控制
trait MyClass1{
function SaySomeThing1(){
echo "MyClass1-SaySomeThing1()<br>";
}
function SaySomeThing2(){
echo "MyClass1-SaySomeThing2()<br>";
}
}
class MyClass{
use MyClass1 {
SaySomeThing1 as protected;
SaySomeThing2 as private SaySomeThing;
}
}
- 在trait中也能使用use来复用其他的trait。