PHP traits (復用機制)

最近在學習Laravel中,遇到了很多關于Traits ,查了下資料,分享下。

提到 php 的代碼復用,我們可能第一時間會想到繼承,但是這種單繼承語言一旦派生的子類過多,那么會產生一系列的問題,比如依賴父類、耦合性太大、破壞了類的封裝性。那么有沒有更好的方法來實現(xiàn)代碼復用呢?

自 PHP 5.4.0 起,PHP 實現(xiàn)了另外一種代碼復用的一個方法,稱為 traits。

Traits 是一種為類似 PHP 的單繼承語言而準備的代碼復用機制。Trait 為了減少單繼承語言的限制,使開發(fā)人員能夠自由地在不同層次結構內獨立的類中復用方法集。Traits 和類組合的語義是定義了一種方式來減少復雜性,避免傳統(tǒng)多繼承和混入類(Mixin)相關的典型問題。

基礎使用方法

Traits 的使用非常簡單,只需要在類中使用 use 關鍵字即可。

trait A {
    public function test() {
        echo 'trait A::test()';
    }
}


class b {
    use A;
}
$b=new b();
$b->test();

優(yōu)先級

簡單來說 Trait 優(yōu)先級大于父類方法,但是小于當前類方法。

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支持抽象方法、支持靜態(tài)方法、不可以直接定義靜態(tài)變量,但靜態(tài)變量可被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 有點相似,都是把一個另外一個對象掛載到當前對象的執(zhí)行環(huán)境當中。當然 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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 前言 眾所周知,一直以來PHP和很多語言一樣是單繼承的語言,但是常常在編碼過程中,我們需要在當前類中使用兩個或兩個...
    金星show閱讀 1,947評論 0 3
  • 面向對象編程之類 定義一個簡單的類 // 定義類,包含field以及方法 // 創(chuàng)建類的對象,并調用其方法 get...
    義焃閱讀 848評論 0 2
  • 1.PHP 對待對象的方式與引用和句柄相同,即每個變量都持有對象的引用,而不是整個對象的拷貝。 2.class 中...
    我在太行山下閱讀 575評論 0 0
  • 作為一種通用開源腳本語言,PHP可以在不同的平臺上運行(Windows、LinuxUnix、MacOS X 等),...
    陽明先生1208閱讀 990評論 1 4
  • 一、php基本語法格式 1.1.簡介 php文件: php能做什么: 運行環(huán)境: 原理:客戶端瀏覽器不能讀取php...
    簡6yao閱讀 429評論 0 0

友情鏈接更多精彩內容