1. 程式人生 > >php trait 學習筆記

php trait 學習筆記

PHP中的類不支援多繼承,但是提供了trait語法類解決單繼承沒法提供的多層程式碼複用問題。

要點:

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 方法又覆蓋了當前類父類中的方法。

<?php 
trait 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 
HelloWorld;
}

class 
MyHelloWorld {
    use 
HelloWorld;
}

$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
?>

輸出結果

Hello World!

6    trait中可以有屬性,靜態方法,抽象方法。