php 代碼複用機制

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

自 PHP 5.4.0 起,PHP 實現了另一種代碼複用的一個方法,稱爲 traits。php

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

基礎使用方法

Traits 的使用很是簡單,只須要在類中使用 use 關鍵字便可。面試

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


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

優先級架構

簡單來講 Trait 優先級大於父類方法,可是小於當前類方法。函數

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衝突問題this

在使用多個 Trait 時,若是其中存在相同的方法名稱,那麼就會產生衝突。使用 insteadof 和 as 能夠解決方法名稱衝突問題code

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支持抽象方法、支持靜態方法、不能夠直接定義靜態變量,但靜態變量可被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 有點類似,都是把一個另一個對象掛載到當前對象的執行環境當中。固然 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

由於 javascript 中的變量環境是基於函數的,因此會輸出a

以上內容但願幫助到你們,不少PHPer在進階的時候總會遇到一些問題和瓶頸,業務代碼寫多了沒有方向感,不知道該從那裏入手去提高,對此我整理了一些PHP高級、架構視頻資料和大廠PHP面試PDF| 免費獲取能夠關注公衆號:PHP開源社區
相關文章
相關標籤/搜索