PHP中物件的引用傳遞

parvin發表於2019-02-16

很多資料型別都可以寫時複製(copy-on-write),如$a=$b,兩個變數賦予的值相等。
對於物件就不一樣:

$box1 = new Parcel();
$box1->destinationCountry = `Denmark`;

$box2 = $box1;
$box2->destinationCountry = `Brazil`;

echo `Parcels need to ship to:` . $box1->destinationCountry . ` and ` . $box2->destinationCountry;
//列印結果 
//Parcels need to ship to: Brazil and Brazil

現在的情況是,當將$box1賦值給$box2時,並沒有複製$box1的值。相反,PHP使用了另一種方式將$box2指向同一個物件,稱其為引用(reference)
通過使用==操作符來比較兩個物件,可以知道它們是否具有相同的類和屬性。

if($box1 == $box2) echo `equivalent`;

還可以更進一步區分它們是否引用同一個原始物件,可用同樣的方式===操作符進行比較:

if($box1 === $box2) echo `exact same object!`;

當兩個變數指向相同的值時,===比較操作符才會返回true。如果物件是完全相同的,但儲存在不同的位置,將返回false。

物件總是通過引用傳遞。即當傳遞一個物件到一個函式中,這個函式會作用於相同的物件,如果這個物件在函式內部發生變化,這種變化會反映到函式外部。這是將一個物件賦值給一個新變數的行為延伸。
物件總是以這樣的方式表現,即它們提供一個對原始物件的引用,而不是建立自己的一個副本

$courier = new PigeonPost(`Avian Delivery Ltd`);

$other_courier = $courier;
$other_courier->name = `Pigeon Post`;

echo $courier->name; // outputs "Pigeon Post"

物件會提供一個指向自己的引用,而不是複製自己的一個副本。這意味著如果一個函式對傳入的一個物件進行操作時,沒有必要從函式中返回。這種變化會在物件的原始副本上反映出來。

如果需要為一個已經存在的物件複製一個單獨的副本,可以使用clone這個關鍵字來建立。

$courier = new PigeonPost(`Avian Delivery Ltd`);

$other_courier = clone $courier;
$other_courier->name = `Pigeon Post`;

echo $courier->name; // outputs "Avian Delivery Ltd"

當複製一個物件時,儲存在其屬性中的任何物件都將是引用而不是副本。
PHP有一個神奇的方法,即如果宣告瞭一個物件,當複製這個物件時,會呼叫這個物件,這就是_clone()方法,你可以宣告而且以此來決定當複製物件時會做什麼,甚至不接受複製

流暢的介面
物件總是通過引用傳遞,這表明無需從一個方法中返回一個物件來觀察它的變化。然而,如果從一個方法中返回$this,可以在應用程式內建立一個流暢的介面(fluent interface),可讓你將方法連結在一起。其工作原理如下:
1.建立物件
2.呼叫物件的方法
3.得到從方法中返回的修正物件
4.選擇返回步驟2

class Parcel
{
    protected $weight;
    protected $destinationCountry;
    
    public function setWeight($weight) {
        echo "weight set to: " . $weight . "
";
        $this->weight = $weight;
        return $this;
    }
    
    public function setCountry($country) {
        echo "destination country is: " . $country . "
";
        $this->destinationCountry = $country;
        return $this;
    }
} 

$myParcel = new Parcel;
$myParcel->setWeight(5)->setCountry(`Peru`);

這裡的關鍵是可以在一行程式碼中呼叫多個方法(可以加一些換行符以增加程式碼的可讀性),並可按任意順序呼叫。由於每個方法都返回生成的物件,因此可以通過返回物件再呼叫下一個方法。

相關文章