我有一个带有返回自己的新实例的方法的类.
这使我可以使用一个对象,而不必一遍又一遍地使用相同的值声明新的对象.对于那些想知道为什么不扩大班级或其他目的的人,这只是使我的生活更轻松,并且它像一种魅力,但是我的最终目的是将它们全部删除.
例如:
$foo = new myClass('name1','ab','cd');
$bar = $foo->duplicate();
//duplicate() saves the new object in itself in an array:
array_push($this->instance,new myClass('name1','ab','cd'));
//and returns a pointer to the saved instance.
return end($this->instance);
$foo和$bar现在共享相同的方法和值,但是可以分别修改这些值.
$foo->changeName('newName');
$bar->changeName('newName2');
我的问题是,如果我取消设置创建的第一个类unset($foo),PHP将自动取消设置其他实例($bar),还是垃圾收集器最终将其删除?
我已经通过使$foo不稳定来测试了它,并在调用$foo时给了我一个错误,但在调用$bar时却没有给我一个错误.
我想做的是立即取消设置该类的所有实例.
谢谢.
解决方法:
自动清理?
不,PHP不了解您的体系结构.它不会删除“级联”对象,它们是独立的实体-例如,可以属于不同的范围.简单的代码:
class Test
{
protected $id = null;
protected $uniqid = null;
public function __construct($id)
{
$this->id = $id;//user-passed variable
$this->uniqid = uniqid();//internal: to identify instance
}
public function getCopy()
{
return new self($this->id);
}
public function getIdentity()
{
return $this->uniqid;
}
}
$foo = new Test(3);
$bar = $foo->getCopy();
var_dump($foo->getIdentity());//valid
unset($foo);
//still valid: bar has nothing to do with foo
var_dump($bar->getIdentity());
顺便说一句,对于复制,您可以在PHP中使用clone
(但是,显然,这将导致对象克隆)
简单的方法
解决问题的最简单方法是遍历$GLOBALS,并使用instanceof
对其进行检查.这具有严重的弱点:内部功能/方法范围将不受影响:
//static since doesn't belong to any instance:
public static function cleanup()
{
foreach($GLOBALS as $name=>$var)
{
if($var instanceof self)
{
unset($GLOBALS[$name]);
}
}
}
-和
$foo = new Test(3);
$bar = $foo->getCopy();
var_dump($foo->getIdentity(), $bar->getIdentity());//valid
Test::cleanup();
//2 x notice:
var_dump($foo, $bar);
请注意,这与“子级”机制无关(即,它将清除全局范围内的所有实例-无论从哪个副本中复制了该实例).
常见情况
上面的示例在通常情况下不会做这些事情.为什么?想象一下,您将拥有持有人类别:
class Holder
{
protected $obj = null;
public function __construct($obj)
{
$this->obj = $obj;
}
public function getData()
{
return $this->obj;
}
}
然后将实例传递给它:
$foo = new Test(3);
$bar = $foo->getCopy();
$baz = new Holder($bar);
-因此,在通常情况下,即使是这种简单情况,您也没有机会处理.而在更复杂的情况下,您也将陷于困境.
该怎么办?
我建议:在需要时明确销毁对象.隐式未设置是一个副作用,即使您将以某种方式保持该状态(我可以想象Observer对其进行某些全局注册表设置)-这将是可怕的副作用,这将破坏代码的可读性.关于代码的问题也是如此,它使用了我上面编写的$GLOBALS-无论如何,我不建议您这样做.