欢迎光临

__construct() 和 __destory() 在 PHP 中需要注意的地方

  

基原上一切的编程谈话在类中城市有结构函数和析构函数的观念。结构函数是在函数实例创造时不妨用来干一些初始化的处事,而析构函数则不妨在实例毁灭前干一些清算处事。相对于来说,结构函数咱们运用得十分多,而析构函数则普遍会用在释搁资材上,例如数据库链交、文献读写的句柄等。

结构函数与析构函数的运用

咱们先来瞅瞅平常的结构与析构函数的运用:

class A
{
    public $name;
    public function __construct($name)
    {
        $this->name = $name;
        echo "A:结构函数被挪用,{$this->name}", PHP_EOL;
    }
    public function __destruct()
    {
        echo "A:析构函数被挪用,{$this->name}", PHP_EOL;
    }
}
$a = new A('$a');
echo '-----', PHP_EOL;
class B extends A
{
    public function __construct($name)
    {
        $this->name = $name;
        parent::__construct($name);
        echo "B:结构函数被挪用,{$this->name}", PHP_EOL;
    }
    public function __destruct()
    {
        parent::__destruct();
        echo "B:析构函数被挪用,{$this->name}", PHP_EOL;
    }
}
class C extends A
{
    public function __construct($name)
    {
        $this->name = $name;
        echo "C:结构函数被挪用,{$this->name}", PHP_EOL;
    }
    public function __destruct()
    {
        echo "C:析构函数被挪用,{$this->name}", PHP_EOL;
    }
}
class D extends A
{
}
// unset($a); // $a的析构提早
// $a = null; // $a的析构提早
$b = new B('$b');
$c = new C('$c');
$d = new D('$d');
echo '-----', PHP_EOL;exit;
// A:结构函数被挪用,$a
// -----
// A:结构函数被挪用,$b
// B:结构函数被挪用,$b
// C:结构函数被挪用,$c
// A:结构函数被挪用,$d
// -----
// A:析构函数被挪用,$d
// C:析构函数被挪用,$c
// A:析构函数被挪用,$b
// B:析构函数被挪用,$b
// A:析构函数被挪用,$a

上头的代码是不是有一些实质和咱们的预期不太普遍?没事,咱们一个一个来瞅:

子类假如沉写了父类的结构大概析构函数,假如不显式地运用parent::__constuct()挪用父类的结构函数,那么父类的结构函数不会实行,如C类子类假如不沉写结构大概析构函数,则默许挪用父类的析构函数假如没显式地将变量置为NULL大概者运用unset()的话,会在足原实行完毕落后行挪用,挪用程序在尝试代码中是相似于栈的方式进步后出(C->B->A,C先被析构),然而在效劳器情况中则不必定,也便是说程序不必定固定

析构函数的引用问题

当对于象中包括自己彼此的引用时,想要经过树立为NULL大概者unset()来挪用析构函数大概会涌现问题。

class E
{
    public $name;
    public $obj;
    public function __destruct()
    {
        echo "E:析构函数被挪用," . $this->name, PHP_EOL;
        echo '-----', PHP_EOL;
    }
}
$e1 = new E();
$e1->name = 'e1';
$e2 = new E();
$e2->name = 'e2';
$e1->obj = $e2;
$e2->obj = $e1;

相似于如许的代码,$e1和$e2都是E类的对于象,他们又各矜持有对于方的引用。本来简略点来说的话,本人持有本人的引用城市涌现相似的问题。

$e1 = new E();
$e1->name = 'e1';
$e2 = new E();
$e2->name = 'e2';
$e1->obj = $e2;
$e2->obj = $e1;
$e1 = null;
$e2 = null;
// gc_collect_cycles();
$e3 = new E();
$e3->name = 'e3';
$e4 = new E();
$e4->name = 'e4';
$e3->obj = $e4;
$e4->obj = $e3;
$e3 = null;
$e4 = null;
echo 'E destory', PHP_EOL;

假如咱们不挨启gc_collect_cycles()那一行的解释,析构函数实行的程序是如许的:

// 不运用gc接收的截止
// E destory
// E:析构函数被挪用,e1
// -----
// E:析构函数被挪用,e2
// -----
// E:析构函数被挪用,e3
// -----
// E:析构函数被挪用,e4
// -----

假如咱们挨启了gc_collect_cycles()的解释,析构函数的实行程序是:

// 运用gc接收后截止
// E:析构函数被挪用,e1
// -----
// E:析构函数被挪用,e2
// -----
// E destory
// E:析构函数被挪用,e3
// -----
// E:析构函数被挪用,e4
// -----

不妨瞅出,必须要让php运用gc接收一次,决定对于象的引用都被释搁了之后,类的析构函数才会被实行。引用假如不释搁,析构函数是不会实行的。

结构函数的矮版原兼容问题

在PHP5往日,PHP的结构函数是与类名共名的一个方式。也便是说假如尔有一个F类,那么function F(){}方式便是它的结构函数。为了向矮版原兼容,PHP依旧保持了这个个性,在PHP7以来假如有与类名共名的方式,便会报落伍正告,然而不会作用步调实行。

class F
{
    public function f() 
    {
        // Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; F has a deprecated constructor 
        echo "F:这也是结构函数,与类共名,不区别巨细写", PHP_EOL;
    }
    // function F(){
    //     // Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; F has a deprecated constructor 
    //     echo "F:这也是结构函数,与类共名", PHP_EOL;
    // }
    // function __construct(){
    //     echo "F:这是结构函数,__construct()", PHP_EOL;
    // }
}
$f = new F();

假如__construc()和类共名方式共时存留的话,会优先走__construct()。其余须要注沉的是,函数名不区别巨细写,所以F()和f()方式是普遍的城市成为结构函数。共理,由于不区别巨细写,所以f()和F()是不行共时存留的。天然,咱们都不提议运用类共名的函数来干为结构函数,究竟曾经是落伍的个性了,说大概哪天便被废除了。

结构函数沉载

PHP是不运转方式的沉载的,只支稳健写,便是子类沉写父类方式,然而不行界说多个共名方式而参数不共。在Java等谈话中,沉载方式十分便利,特殊是在类实例化时,不妨便利地实行多态本领。

$r1 = new R(); // 默许结构函数
$r2 = new R('arg1'); // 默许结构函数 一个参数的结构函数沉载,arg1
$r3 = new R('arg1', 'arg2'); // 默许结构函数 二个参数的结构函数沉载,arg1,arg2

便像上述代码普遍,假如你试验界说多个__construct(),PHP会很直交地告知你运转不了。那么有不其余方式实行上述代码的功效呢?天然有,不然咱也不会写了。

class R
{
    private $a;
    private $b;
    public function __construct()
    {
        echo '默许结构函数', PHP_EOL;
        $argNums = func_num_args();
        $args = func_get_args();
        if ($argNums == 1) {
            $this->constructA(...$args);
        } elseif ($argNums == 2) {
            $this->constructB(...$args);
        }
    }
    public function constructA($a)
    {
        echo '一个参数的结构函数沉载,' . $a, PHP_EOL;
        $this->a = $a;
    }
    public function constructB($a, $b)
    {
        echo '二个参数的结构函数沉载,' . $a . ',' . $b, PHP_EOL;
        $this->a = $a;
        $this->b = $b;
    }
}
$r1 = new R(); // 默许结构函数
$r2 = new R('arg1'); // 默许结构函数 一个参数的结构函数沉载,arg1
$r3 = new R('arg1', 'arg2'); // 默许结构函数 二个参数的结构函数沉载,arg1,arg2

相对于来说比Java之类的谈话要烦恼一些,然而是也真实是实行了相通的功效哦。

结构函数和析构函数的考察节制

结构函数和析构函数默许都是public的,和类中的其余方式默许值普遍。天然它们也不妨树立成private和protected。假如将结构函数树立成非大众的,那么你将无法实例化这个类。这一点在单例形式被广大运用,底下咱们直交经过一个单例形式的代码可见。

class Singleton
{
    private static $instance;
    public static function getInstance()
    {
        return self::$instance == null ? self::$instance = new Singleton() : self::$instance;
    }
    private function __construct()
    {
    }
}
$s1 = Singleton::getInstance();
$s2 = Singleton::getInstance();
echo $s1 === $s2 ? 's1 === s2' : 's1 !== s2', PHP_EOL;
// $s3 = new Singleton(); // Fatal error: Uncaught Error: Call to private Singleton::__construct() from invalid context

当$s3想要实例化时,直交便报错了。闭于单例形式为什么要让外部无法实例化的问题,咱们不妨瞅瞅之前的安排形式体系文章中的单例形式。

归纳

没料到咱们每天用到的结构函数还能玩出如许多款式来吧,凡是在启垦中比拟须要注沉的便是子类继续时对于结构函数沉写时父类结构函数的挪用问题以及引用时的析构问题。

投稿 :《前沿资讯

以上便是__construct() 和 __destory() 在 PHP 中须要注沉的场合的仔细实质,更多请闭心赢咖3http://www.gjbl.net) 其余相干文章!

下一篇:PHP生命周期

关于“__construct() 和 __destory() 在 PHP 中需要注意的地方”的评论:

  • 访客默认头像 访客-cons 发表于:2020年07月05日 8334aaa0?句柄等。

    class A {

  • 访客默认头像 访客-用户193 发表于:2020年07月05日 念。结构函——__constr。相对于来说,结构函数咱们运用得十分多,而析构函数则普遍会用。
  • 访客默认头像 访客- __d 发表于:2020年07月05日 (,name) { !t::__destruct(); 。。。

发表评论

必填

选填

选填

◎欢迎参与讨论,发表不一样的看法,秀出你的风采。