Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> PHP

Sao chép đối tượng (Object Cloning) trong PHP

Giới thiệu

Tạo bản sao đối tượng bằng phép gán đơn giản chỉ tạo thêm một tham chiếu đến cùng đối tượng trong bộ nhớ. Do đó, thay đổi thuộc tính sẽ phản ánh cả trong đối tượng gốc và bản sao. PHP có từ khóa clone tạo bản sao nông (shallow copy). Tuy nhiên, nếu đối tượng gốc có đối tượng nhúng (embedded object) làm thuộc tính, bản sao vẫn tham chiếu đến cùng đối tượng nhúng đó. Để tạo bản sao sâu (deep copy), phương thức ma thuật __clone() cần được định nghĩa trong lớp.

Sao chép bằng phép gán (Assignment)

Trong mã sau, myclass có thuộc tính là đối tượng của lớp address. Đối tượng myclass được sao chép bằng phép gán. Thay đổi giá trị thuộc tính phản ánh trong cả hai đối tượng:

<?php
class address {
    var $city = "Nanded";
    var $pin = "431601";
    function setaddr($arg1, $arg2) {
        $this->city = $arg1;
        $this->pin = $arg2;
    }
}
class myclass {
    var $name = "Raja";
    var $obj;
    function setname($arg) {
        $this->name = $arg;
    }
}
$obj1 = new myclass();
$obj1->obj = new address();
echo "original object\n";
print_r($obj1);
$obj2 = $obj1;
$obj1->setname("Ravi");
echo "after change:\n";
print_r($obj1);
print_r($obj2);
?>

Kết quả

original object
myclass Object(
    [name] => Raja
    [obj] => address Object(
        [city] => Nanded
        [pin] => 431601
    )
)
after change:
original object
myclass Object(
    [name] => Ravi
    [obj] => address Object(
        [city] => Nanded
        [pin] => 431601
    )
)
copied object
myclass Object(
    [name] => Ravi
    [obj] => address Object(
        [city] => Nanded
        [pin] => 431601
    )
)

Sử dụng từ khóa clone

Từ khóa clone tạo bản sao nông (shallow copy). Thay đổi thuộc tính kiểu giá trị không phản ánh trong đối tượng clone. Tuy nhiên, nếu đối tượng nhúng bị sửa đổi, thay đổi sẽ phản ánh cả trong đối tượng gốc và clone:

<?php
class address {
    var $city = "Nanded";
    var $pin = "431601";
    function setaddr($arg1, $arg2) {
        $this->city = $arg1;
        $this->pin = $arg2;
    }
}
class myclass {
    var $name = "Raja";
    var $obj;
    function setname($arg) {
        $this->name = $arg;
    }
}
$obj1 = new myclass();
$obj1->obj = new address();
echo "original object:\n";
print_r($obj1);
$obj2 = clone $obj1;
$obj1->setname("Ravi");
$obj1->obj->setaddr("Mumbai", "400001");
echo "after change:\n";
echo "original object:\n";
print_r($obj1);
echo "cloned object:\n";
print_r($obj2);
?>

Kết quả

original object:
myclass Object(
    [name] => Raja
    [obj] => address Object(
        [city] => Nanded
        [pin] => 431601
    )
)
after change:
original object:
myclass Object(
    [name] => Ravi
    [obj] => address Object(
        [city] => Mumbai
        [pin] => 400001
    )
)
cloned object:
myclass Object(
    [name] => Raja
    [obj] => address Object(
        [city] => Mumbai
        [pin] => 400001
    )
)

Chú ý: Thuộc tính name (giá trị nguyên thủy) không bị ảnh hưởng, nhưng obj (đối tượng nhúng) vẫn chung tham chiếu.

Sử dụng phương thức __clone() để tạo bản sao sâu (Deep copy)

Phương thức __clone() tạo bản sao sâu bằng cách clone cả đối tượng nhúng:

<?php
class address {
    var $city = "Nanded";
    var $pin = "431601";
    function setaddr($arg1, $arg2) {
        $this->city = $arg1;
        $this->pin = $arg2;
    }
}
class myclass {
    var $name = "Raja";
    var $obj;
    function setname($arg) {
        $this->name = $arg;
    }
    public function __clone() {
        $this->obj = clone $this->obj;
    }
}
$obj1 = new myclass();
$obj1->obj = new address();
echo "original object:\n";
print_r($obj1);
$obj2 = clone $obj1;
$obj1->setname("Ravi");
$obj1->obj->setaddr("Mumbai", "400001");
echo "after change:\n";
echo "original object:\n";
print_r($obj1);
echo "cloned object:\n";
print_r($obj2);
?>

Kết quả

original object:
myclass Object(
    [name] => Raja
    [obj] => address Object(
        [city] => Nanded
        [pin] => 431601
    )
)
after change:
original object:
myclass Object(
    [name] => Ravi
    [obj] => address Object(
        [city] => Mumbai
        [pin] => 400001
    )
)
cloned object:
myclass Object(
    [name] => Raja
    [obj] => address Object(
        [city] => Nanded
        [pin] => 431601
    )
)

Bây giờ cả name và obj đều độc lập hoàn toàn giữa bản gốc và bản clone.