9

如何启动由 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 类的构造函数是显式调用的。有没有办法做到这一点?

4

3 回答 3

6

当类被组合时,C 的构造函数和析构函数将优先于 trait 构造函数和析构函数:

从基类继承的成员被由 Trait 插入的成员覆盖。优先顺序是当前类中的成员覆盖 Trait 方法,这反过来又覆盖继承的方法。

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

换句话说,从 C 中删除空的构造函数和析构函数,就会使用 trait 的构造函数和析构函数。无法同时使用 C 和特征,构造函数和析构函数,因为特征不像常规继承那样工作。

一般来说,我建议不要给 Traits 自己的构造函数或析构函数,因为你不能实例化 Traits。您从具有Trait的类进行实例化,并且该类应该处于控制之中。考虑将onCreate()oronDestroy()方法添加到特征中,并从 C 上适当的魔术方法调用这些方法。您可以通过在 C 中为特征 __construct 起别名来实现相同的目的,但我认为这会淡化语义。

于 2013-01-04T12:38:35.957 回答
3

您必须为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();
    }
}
于 2016-12-02T19:21:08.600 回答
3

除了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::__construct() 完成
T1::__construct() 完成
T2::__construct() 完成
C2::__construct() 完成
0b10100011

于 2016-12-18T17:17:11.893 回答