次のようなPHPコードがあります。
class A {
public function __construct() {
$this->b = new B(function($x) { return $x + 1; });
}
};
class B {
public function __construct($dataProcessingFunction) {
$this->dataProcessingFunction = $dataProcessingFunction;
}
public function processData($data) {
$f = $this->dataProcessingFunction;
return $f($data);
}
};
しかし、問題があります。A のデストラクタの前に B のデストラクタを呼び出す必要があります。ご覧のとおり、これは合理的なようです。B オブジェクトは A を必要としないので、問題はないはずです。
しかし、PHP 5.4.0 以降、クロージャは暗黙的に $this を自動的にキャプチャするようになりました。したがって、B に渡し、B によって格納されるラムダ関数には、A への参照が含まれています。
つまり、A には B へのポインターが含まれ、B には (クロージャーを介して) A へのポインターが含まれます。この種の状況では、デストラクタはガベージ コレクションでランダムな順序でのみ呼び出されると PHP のドキュメントに記載されています。B のデストラクタは常に A の前に呼び出されます。
これをエレガントな方法で解決する方法はありますか?