2013-01-04 80 views
7

如何啓動trait定義的構造函數和析構函數以及類的構造函數和析構函數。例如,特性定義的構造函數/析構函數沒有被調用

trait Audit 
{ 
    public function __construct() 
    { 
     parent::__construct(); // Doesn't work... 

     $this->_name = __CLASS__; 

     $this->AuditAction('Started'); 
    } 

    public function __destruct() 
    { 
     parent::__destruct(); // Doesn't work... 

     $this->AuditAction('Ended'); 

     echo $this->_log;   
    } 

    public function AuditAction($n) 
    { 
     $this->_log .= $this->GetCurrentTimeStamp() . ' ' . $this->_name . ": $n" . PHP_EOL; 
    } 

    private function GetCurrentTimeStamp() 
    { 
     return (new DateTime())->format('[Y-m-d H:i:s]'); 
    } 

    private $_name, $_log = ''; 
} 

class C 
{ 
    use Audit; 

    public function __construct() 
    { 

    } 

    public function __destruct() 
    { 

    } 
} 

$c = new C();

我應該得到幾行文本,但我沒有得到任何東西,因爲C類的構造函數被顯式調用。有沒有辦法做到這一點?

回答

5

C的構造函數和析構函數將具有優先於特徵構造函數和析構函數當類組成:

的繼承從基類構件通過由特質插入的構件覆蓋。 優先順序是來自當前類的成員重寫Trait方法,它在返回時重寫繼承的方法。

來源:http://php.net/traits

換句話說,由C取出空構造函數和析構函數和性狀的構造函數和析構函數將被使用。沒有辦法使這兩種工作,C和性狀,Ctor和Dtor,因爲特質不像常規繼承。

一般來說,我建議不要給traits自己的ctors或dtors,因爲你不能實例化traits。你從具有特性的類實例化,並且該類應該處於控制之下。考慮向該特徵添加一個onCreate()onDestroy()方法,並從C上適當的魔術方法調用這些方法。您可以通過在C中混淆特徵__construct來實現同樣的效果,但我認爲這會降低語義。

+0

這是不正確的。可以調用被使用特徵的類覆蓋的特徵的方法。用其他的東西來改變Trait中方法的名字就足夠了。 – Aerendir

+0

@Aerendir如果我對C源的閱讀是正確的,那麼別名ctor或dtor將不再包含ctor或dtor函數標誌。這意味着它在技術上*不可能*,因爲它們只是常規方法。然而,你顯然是正確的,你可以通過別名來執行它們*作爲常規方法*,這將有效解決OP的問題。但更像是調用一個自定義的'onCreate()'或'onDestroy()'方法,而不是調用實際的ctors或dtors。 – Gordon

2

您必須爲Trait的方法定義自定義名稱。然後你可以從你的班級調用這些方法。

由於類的方法覆蓋的方法Trait你有不同的名稱分配給Trait的方法:

class C 
{ 
    use Audit { 
     Audit::__construct as auditConstruct; 
     Audit::__destruct as auditDestruct; 
    } 

    public function __construct() 
    { 
     $this->auditConstruct(); 
    } 

    public function __destruct() 
    { 
     $this->auditDestruct(); 
    } 
} 
2

加成Aeremdir的回答是:從基類繼承構造函數和多個性狀...

<?php 
    trait T1 { 
    public function __construct() { 
     $this->someval |= 0b0001; 
     echo "T1::__construct() done\n"; 
    } 
    } 

    trait T2 { 
    public function __construct() { 
     $this->someval |= 0b0010; 
     echo "T2::__construct() done\n"; 
    } 
    } 

    class C1 { 
    protected $someval; 

    public function __construct() { 
     $this->someval = 0b10000000; 
     echo "C1::__construct() done\n"; 
    } 
    } 

    class C2 extends C1 { 
    use T1, T2 { 
     T1::__construct as private T1__construct; 
     T2::__construct as private T2__construct; 
    } 

    public function __construct() { 
     parent::__construct(); 
     $this->T1__construct(); 
     $this->T2__construct(); 

     $this->someval |= 0b00100000; 
     echo "C2::__construct() done\n"; 
    } 

    public function someval() { 
     $str = base_convert($this->someval, 10, 2); 
     $len = strlen($str); 
     if($len < 8) 
      $str = str_repeat('0', 8 - $len) . $str; 

     return '0b' . $str; 
    } 
    } 

    $v1 = new C2(); 
    echo $v1->someval(); 
?> 

下PHP 7.0.5本規範的結果...

C1 :: __構建體()來完成
T1 :: __構建體()來完成
T2 :: __構建體()來完成
C2 :: __構建體()來完成
0b10100011

相關問題