魔術方法(__tostring(),__set_state())

看下面這段代碼:

?
1
2
3
4
5
6
7
8
class Test{
    public $a;
    public function func(){
        echo '我只是一個字符串';
    }
}
$test = new Test();
echo $test;

輸出的內容爲:Catchable fatal error: Object of class Test could not be converted to string in G:\xampp\htdocs\www\testclass.php on line 10

如果我們想打印出一個對象,就需要調用__toString()這個魔術方法了,我們給他加上一個__toString()就不會出錯了。

?
1
2
3
4
5
6
7
8
9
10
11
12
class Test{
    public $a;
    public function func(){
        echo '我只是一個字符串';
    }
     
    public function __toString(){
        return "你在打印一個對象的方法";
    }
}
$test = new Test();
echo $test;

會輸出: 你在打印一個對象的方法

__set_state()

這個方法其實也比較簡單,就是var_export()的回調函數。看下面這段代碼

?
1
2
3
4
5
6
7
8
class Test{
    public $a;
    public function func(){
        echo '我只是一個方法';
    }
}
$test = new Test();
var_export($test);

會輸出: Test::__set_state(array( 'a' => NULL, ))

注意a是NULL,沒有賦值,下面我寫個回調

?
1
2
3
4
5
6
7
8
9
10
11
12
class Test{
    public $a;
    static function __set_state($array) {//必須是靜態方法,參數是一個數組
        $tmp = new Test();
        $tmp->a = 'abc';//直接賦值
        return $tmp;//必須返回一個對象,可以是其他類的對象
    }
     
}
$test = new Test();
eval('$b = '.var_export($test,true).';');
var_dump($b);

輸出的內容爲: object(Test)#2 (1) { ["a"]=> string(3) "abc" }

有人問這有什麼用?是沒多大用,最大的作用可以複製一個對象。只需改下代碼而已。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
class Test{
    public $a;
    static function __set_state($array) {//必須是靜態方法,參數是一個數組
        $tmp = new Test();
        $tmp->a = $array['a'];//直接賦值
        return $tmp;//必須返回一個對象,可以是其他類的對象
    }
     
}
$test = new Test();
$test->a = '我是$test';
eval('$b = '.var_export($test,true).';');
var_dump($b);

會輸出: object(Test)#2 (1) { ["a"]=> string(11) "我是$test" }

有人又會問了,克隆可以直接clone()方法啊!!那麼好,這樣的情況請問你如何克隆,我們來看下代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
class Test{
    public $a;
    static function __set_state($array) {//必須是靜態方法,參數是一個數組
        $tmp = new Test();
        $tmp->a = str_replace('$test','$b',$array['a']);//直接賦值
        return $tmp;//必須返回一個對象,可以是其他類的對象
    }
     
}
$test = new Test();
$test->a = '我是$test';
eval('$b = '.var_export($test,true).';');
var_dump($b);

這樣的話,我們雖然克隆了一個$test,但是我們又做了相應的改變。

有的人問,你爲什麼不用__clone進行回調呢?這正是我想說的地方,個人認爲__clone() 沒有 __set_state()強大,因爲__clone()沒有可以接受的參數,侷限了“進化”的範圍,我用個例子說明。

?
1
2
3
4
5
6
7
8
9
10
11
class Test{
    public $a;
    function __clone(){
        $this->a = str_replace('a','克隆a',$this->a);//無法通過參數改變a
    }
     
}
$test = new Test();
$test->a = '我是a';
$b = clone $test;
var_dump($b);

輸出的結果是: object(Test)#2 (1) { ["a"]=> string(13) "我是克隆a" }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章