PHP的一些高級特性

自定義__clone()復(fù)制對象

class Person{
    public $name;
    public function __construct($name) {
        $this->name = $name;
    }
}
$first = new Person("zhangsan");
$second = $first;

如上例,PHP4時代$second和$first是兩個完全不同的對象,php5之后$second和$first指向同一個對象。但對于基本數(shù)據(jù)類型顯然不是引用復(fù)制。

//PHP 5.2.17 (cli) (built: May 26 2015 16:23:47) 
$second->name = "lisi";
var_dump($first === $second);   //true
var_dump($second->name);  //lisi
var_dump($first->name);   //lisi

$third = array(
    "hello" => "world",
);  //分配數(shù)組的空間0x0001,分配變量$third內(nèi)存,并指向0x0001
$fourth = $third;  //分配變量$fourth內(nèi)存,并指向同一地址0x0001,引用計數(shù)加1
var_dump($fourth === $third);   //true,內(nèi)容相同,內(nèi)容地址也相同
$fourth['hello'] = "fuck";  //變量改變,重新copy一份出來,給$fourth指向,并修改引用計數(shù)
var_dump($fourth === $third);   //false,已經(jīng)是不同的內(nèi)容,不同的地址

這就很尷尬了,雖然引用復(fù)制較為節(jié)省空間,但有時我們希望對象的復(fù)制是值copy,各自保留各自的副本。php提供的clone關(guān)鍵字能夠解決該問題。

$first = new Person("zhangsan");
$second = clone $first;  //各自有一份TestPHP的副本
var_dump($first === $second);   //false,地址不同
$second->name = "lisi";  //修改的是自己的TestPHP對象內(nèi)容
var_dump($second->name);  //lisi
var_dump($first->name);  //zhangsan

尷尬的事又出現(xiàn)了,一個clone把事都辦了,那還有啥高級特性?我們?nèi)绻远x對象的copy呢?比如我希望在復(fù)制Person的時候,除id以外的信息,而id要初始化成0。那就需要自定義對象的clone了。

class Person{
    public $id;
    public $name;
    function __construct($id,$name) {
        $this->id = $id;
        $this->name = $name;
    }
    public function __clone() {
        $this->id = 0;
    }
}
$first = new Person("1", "zhangsan");
$second = clone $first;
var_dump($second->id . " | " . $second->name);  //0 | zhangsan
var_dump( $first->id . " | " . $first->name );  //1 | zhangsan

這時Account加入了戰(zhàn)斗,問題又出現(xiàn)了。

class Account {
    public $balance;
    function __construct($balance) {
        $this->balance = $balance;
    }
}
class Person {
    public $id;
    public $name;
    public $account;
    function __construct($id, $name, Account $account) {
        $this->id = $id;
        $this->name = $name;
        $this->account = $account;
    }
    public function __clone() {
        $this->id = 0;
    }
}
$first = new Person("1", "zhangsan", new Account(100));
$second = clone $first;
$first->account->balance += 10000;
var_dump($first->account->balance); // 10100
var_dump($second->account->balance); //10100

$first、$second初始化賬戶上應(yīng)該又100元,現(xiàn)在給$first充了10000,結(jié)果$second的賬戶上也被加了10000,,因為在clone Person對象時,account變量的復(fù)制仍然是引用復(fù)制,導(dǎo)致問題,需修改__clone方法

function __clone() {
    $this->id = 0;
    $this->account = clone $this->account;
}

__autoload()與spl_autoload_register()實現(xiàn)自動加載

PHP5引入了__autoload()攔截器方法實現(xiàn)類文件的自動加載,需要自定義加載函數(shù),其實就是說清楚在php執(zhí)行過程中,遇到未定義的類,到哪兒取找該類的實現(xiàn)文件。

$testLoad = new TestLoad();  //Fatal error: Class 'TestLoad' not found in XXXXX
$testLoad->say(); 

但是如果自定義實現(xiàn)了__autoload()方法,方法需要傳遞className作為參數(shù)名,然后找到TestLoad類的實現(xiàn),加載類,實例化,調(diào)用say()方法就ok。

function __autoload($className) {
    require_once "$className.php";  //自己定義,想加載什么文件、想到哪兒加載文件都是自己定義
}
$testLoad = new TestLoad();
$testLoad->say();  //hello,world

TestLoad類的實現(xiàn)

class TestLoad {
    public function say() {
        echo "hello,world" . PHP_EOL;
    }
}

spl_autoload_register()方法又是干啥的呢? 這么理解,__autoload()方法是正規(guī)軍,系統(tǒng)是認(rèn)識它的,你只要敢定義它,就能實現(xiàn)類的自動加載。但是如果地方軍呢?比如我想起個名字叫XX()的加載函數(shù),就需要使用spl_autoload_register()去登記注冊告訴系統(tǒng)這是自己人,以后遇到未定義類的時候,找XX就行了。

function myLoad($className) {
    require_once "$className.php";
}
spl_autoload_register("myLoad");
$testLoad = new TestLoad();
$testLoad->say();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容