<?php
/*抽象原型类*/
abstract class Prototype {
abstract function __clone();
}
class Map extends Prototype {
public $width;
public $height;
public $sea;
public function __conturct() {
echo '我初始化了';
}
public function setAttribute(array $conllection) {
foreach ($conllection as $key => $val) {
$this->$key = $val;
}
}
/*浅拷贝*/
public function __clone() {}
/*深度拷贝*/
// public function __clone() {
// $this->sea = clone $this->sea;
// }
/**
*推荐的深度拷贝
* serialize() 返回字符串,此字符串包含了表示 value 的字节流,可以存储于任何地方。
* 这有利于存储或传递 PHP 的值,同时不丢失其类型和结构。
* unserialize() 对单一的已序列化的变量进行操作,将其转换回 PHP 的值。
* */
// public function __clone() {
// $serialize_obj = serialize($this->sea); //序列化
// $this->sea = unserialize($serialize_obj); //反序列化
// }
}
class Sea {
// public $fish;
// public function __construct($fish) {
// $this->fish = $fish;
// }
}
$map_protype = new Map();
$sttributes = array('width' => 40, 'height' => 60, 'sea' => (new Sea()));
$map_protype->setAttribute($sttributes);
$new_map = clone $map_protype;
var_dump($map_protype);
echo '<br>';
var_dump($new_map);
echo '<br>';
echo '<br>';
echo '<br>';
$new_map->width = 80;
var_dump($map_protype);
echo '<br>';
var_dump($new_map);
/*但是上面的代码还是存在一些问题。那就是它只是一个浅拷贝,
什么意思呢?map原型对象有一个属性sea存放了一个sea对象,
在调用setAttribute的时候,对象的赋值方式默认是引用。而当
我们克隆map对象时,直接克隆了map的sea属性,这就使得克
隆出来的对象与原型对象的sea属性对指向了,同一个sea对象
的内存空间。如果这个时候,我们改变了克隆对象的sea属性,
那么原型对象的sea属性也跟着改变*/
echo '<br>';
echo '<br>';
echo '<br>';
$new_map->sea->d = 80;
var_dump($map_protype);
echo '<br>';
var_dump($new_map);
$map_protype = new Map();
$sttributes = array('width' => 40, 'height' => 60, 'sea' => (new Sea('鱼')));
$map_protype->setAttribute($sttributes);
$new_map = clone $map_protype;
var_dump($map_protype);
var_dump($new_map);
$map_protype->sea->fish = "大鱼";
var_dump($map_protype);
echo '</br>';
var_dump($new_map);
网友评论