最近,在尝试不同的依赖注入方法时,我偶然发现了一个概念,在这个概念中,我可能有相互引用的类。
例如,当尝试从视图、模型或控制器对象访问数据库对象时,我想这可能非常有用。
但我只是想知道会不会有陷阱?
比如内存泄漏等等。
如果这是一个愚蠢的问题,很抱歉,但无论如何,这个想法对我来说都是新的。
class foo{
public $bar;
}
class bar{
public $foo;
public function __construct($foo) {
$this->foo=$foo;
$this->foo->bar=$this;
}
}
$foo = new foo;
$bar = new bar($foo);
var_dump($foo->bar->foo->bar->foo->bar->foo);
// object(foo)#1 (1) {
// ["bar"]=>
// object(bar)#5 (1) {
// ["foo"]=>
// *RECURSION*
// }
// }
这在任何语言中都是一种代码气味。应不惜一切代价避免循环依赖。解决方案通常是将共享的依赖关系抽象为一个不依赖于任何东西本身的公共类。
您给出的示例有些人为,但一般来说,具有相互引用的类实例是完全有效的。
例如,如果您开发了一个解析器,那么在构建解析树时,会出现许多类似的情况。
为了进行详细说明,请考虑以下从用PHP编写的Nikic优秀PHP解析器中提取的类:https://github.com/nikic/PHP-Parser
您将看到PHPParser_Node_Expr_Array
的一个实例,它显然可以出现在PHPParser_Node_Expr
中,并在array
字段中引用其他PHPParser_Node_Expr
实例。
<?php
/**
* @property PHPParser_Node_Expr_ArrayItem[] $items Items
*/
class PHPParser_Node_Expr_Array extends PHPParser_Node_Expr
{
/**
* Constructs an array node.
*
* @param PHPParser_Node_Expr_ArrayItem[] $items Items of the array
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(array $items = array(), $line = -1, $docComment = null) {
parent::__construct(
array(
'items' => $items
),
$line, $docComment
);
}
}
PHP 5.3之前的PHP垃圾收集器无法解析循环引用,因此无法释放为这些对象和整个对象连接图分配的内存。
现在问题解决了:http://php.net/manual/en/features.gc.collecting-cycles.php
一定要尽量避免代码过于复杂。