php trait 學習筆記
PHP中的類不支援多繼承,但是提供了trait語法類解決單繼承沒法提供的多層程式碼複用問題。
要點:
1 Trait 不能通過它自身來例項化,但可以在類中使用,也可以通過靜態呼叫使用trait中方法和屬性。
<?php
trait T{
public function t_method(){
echo "this is t_method<br>";
}
}
class C{
//在類中使用trait
use T;
public function c_method(){
echo "this is c_method<br>";
}
}
$cls= new C();
$cls->t_method();
//通過類呼叫
$cls->c_method();
//靜態呼叫
T::t_method();
?>
輸出結果:
this is t_method
this is c_method
this is t_method
2 在類中使用trait,如果出現類的函式或屬性於trait的函式或屬性同名,就回會發生覆蓋---》當前類中的方法會覆蓋 trait 方法,而 trait 方法又覆蓋了當前類父類中的方法。
<?phptrait T{
public function sameWithBase(){
echo "this is trait's sameWithBase()<br>";
}
public function commonMethod(){
echo "this is trait's commonMethod()<br>";
}
}
class base{
public function sameWithBase(){
echo "this is base's sameWithBase()<br>";
}
public function commonMethod(){
echo "this is base's commonMethod()<br>";
}
}
class C extends base{
use T;
public function commonMethod(){
echo "this is class's commonMethod()<br>";
}
}
$cls=new C();
//trait方法覆蓋父類方法
$cls->sameWithBase();
//當前類方法覆蓋trait方法
$cls->commonMethod();?>
輸出結果
this is trait's sameWithBase()
this is class's commonMethod()
3 可以在同一個類中使用多個Trait,如果出現多個Trait中有函式或屬性同名的情況,執行時就會報錯。有兩種方式解決,A方式:需要使用 insteadof 操作符來明確指定使用衝突方法中的哪一個 ,B方式:使用as 操作符可以將其中一個衝突的方法以另一個名稱來引入。
<?php
trait T1{
public function sameName1(){
echo "this is T1's sameName1()<br>";
}
public function sameName2(){
echo "this is T1's sameName2()<br>";
}
}
trait T2{
public function sameName1(){
echo "this is T2's sameName1()<br>";
}
public function sameName2(){
echo "this is T2's sameName2()<br>";
}
}
class C{
use T1,T2{
//如果每個方法的作用都不同,那C使用T1,T2後,按理將會擁有4個方法。
//但是因為有同名方法,如果C只用sameName1()和sameName2()兩個函式名,那C只能有擁有兩個方法,
//而且呼叫sameName1()和sameName2()時程式並不知道是T1,還是T2中的,所以,重名的方法必須
//全部指定具體使用的是哪一個!
//需要使用 insteadof 操作符來明確指定使用衝突方法中的哪一個。
T1::sameName1 insteadof T2;
T2::sameName2 insteadof T1;
//insteadof 必須有name1和name2,否則會報錯
//as 為可選
//B方式在使用時給同名的方法或屬性重新命名
T2::sameName2 as rename;
T2::sameName1 as rename1;
}
}
$cls=new C();
$cls->sameName1();
$cls->sameName2();
$cls->rename();
$cls->rename1();
?>
輸出結果
this is T1's sameName1()
this is T1's sameName2()
this is T2's sameName2()
this is T2's sameName1()
4 在使用時可以修改的訪問屬性。
<?php
trait HelloWorld {
public function sayHello() {
echo 'Hello World!';
}
}
// 修改 sayHello 的訪問控制
class MyClass1 {
use HelloWorld { sayHello as protected; }
}
// 給方法一個改變了訪問控制的別名
// 原版 sayHello 的訪問控制則沒有發生變化
class MyClass2 {
use HelloWorld { sayHello as private myPrivateHello; }
}
?>
5 可以用trait來組合trait。
<?php
trait Hello {
public function sayHello() {
echo 'Hello ';
}
}
trait World {
public function sayWorld() {
echo 'World!';
}
}
trait HelloWorld {
use Hello, World;
}
class MyHelloWorld {
use HelloWorld;
}
$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
?>
輸出結果
Hello World!
6 trait中可以有屬性,靜態方法,抽象方法。