他们说当对象具有循环引用时,这不是一个好主意。让我们看一个复合示例:
class Book
{
private $title;
public function __construct($title)
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
}
class Shelf
{
private $books = [];
public function addBook (Book $book)
{
$this->books[] = $book;
}
}
$shelf = new Shelf();
$sehlf->add (new Book('a'));
$sehlf->add (new Book('b'));
$sehlf->add (new Book('c'));
目前为止,一切都好。出于某种原因,Book
必须了解Shelf
,所以我重写:
class Book
{
private $title;
private $shelf;
public function __construct($title, $shelf)
{
$this->shelf = $shelf;
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
}
class Shelf
{
private $books = [];
public function addBook (Book $book)
{
$this->books[] = $book;
}
}
$shelf = new Shelf();
$sehlf->add (new Book('a', $shelf));
$sehlf->add (new Book('b', $shelf));
$sehlf->add (new Book('c', $shelf));
他们说这很糟糕。
循环引用有几个问题可以在这里找到,但我必须接受上面不是一个非常有问题的例子——因为很明显,在书之前必须先创建书架。
例如,最常见的问题之一是,假设变量是公共的,在上述Book
实例上使用print_r
可能是"不可能的",这将导致内存耗尽。
有几种方法可以解决循环引用问题,最常见的方法之一是使用 Setter 注入。
例如public function setShelf(Shelf $shelf)
{
$this->shelf = $shelf;
}
PHP 的另一个特别问题是,它可能在解决循环依赖关系时遇到问题。例如,请参阅此内容。
class Node {
public $parentNode;
public $childNodes = array();
function Node() {
$this->nodeValue = str_repeat('0123456789', 128);
}
function destroy()
{
$this->parentNode = null;
$this->childNodes = array();
}
}
function createRelationship() {
$parent = new Node();
$child = new Node();
$parent->childNodes[] = $child;
$child->parentNode = $parent;
$parent->destroy();
}
PHP 最终会无缘无故地分配大约 35MB 的内存。为了解决这个问题,我们可以使用析构函数,以便垃圾回收器知道如何在完成对象后处理对象。
function destroy()
{
$this->parentNode = null;
$this->childNodes = array();
}