Если два объекта ссылаются друг на друга, они никогда не будут подвергаться сборке мусора, поскольку всегда будут ссылки на оба. Поэтому я использую слабые ссылки для ссылок на контейнеры. Я создал черту, которая отлично с этим справляется и работает уже много лет.
В конструкторе я могу сделать это:
Код: Выделить всё
class user {
use weakObjReference;
function __construct(users $container) {
$this->weakReference($container, 'container');
// can use $this->container now everywhere; the trait has stored it internally as a WeakReference
// and via __get gives it back as a normal (strong) object reference
}
}
Однако у меня иногда возникают проблемы, когда я создаю экземпляры на лету. Самый простой пример:
Код: Выделить всё
class a {
public readonly b $b;
function __construct(public string $name) {
$this->b = new b($this);
}
function hoohoo(): mixed {
return $this->b;
}
}
class b {
use weakObjReference;
function __construct(a $container) {
$this->weakReference($container, 'container'); // $this->container "created"
}
function heehee($name): mixed {
$x = $name . ', '. $this->container->name;
return $x;
}
}
$a = new a('world 1');
var_dump($a->hoohoo()->heehee('hello')); // EXAMPLE 1
var_dump((new a('world 2'))->hoohoo()->heehee('good afternoon')); // EXAMPLE 2.
ПРИМЕР 1. РАБОТАЕТ. Возвращает «привет, мир 1».
ПРИМЕР 2. ОШИБКА. слабыйObjReferenceStorage::get(): Возвращаемое значение должно иметь тип объекта, возвращаемое значение NULL, другими словами: слабая ссылка недействительна, поскольку экземпляр был удален.
Это означает, что сбор мусора слишком агрессивен для моих целей. Как только heehee() выполняется, экземпляр класса a уже уничтожается, поэтому WeakReference обратно в a больше не работает. Я думал, что сбор мусора будет производиться после утверждения, но видимо сильно ошибаюсь; это делается немедленно, пока оператор еще выполняется.
Я принял некрасивое решение, снова временно сделав экземпляры сильными. Но это неустойчиво для всей системы со многими классами, поскольку требует точного знания, когда сделать ссылку временно сильной, а когда снова слабой для нескольких классов. Чтобы увидеть, насколько это беспорядочно, я добавил уровень контейнеров:
Код: Выделить всё
class a {
public readonly b $b;
function __construct(public string $name) {
$this->b = new b($this);
}
function hoohoo(): mixed {
$this->b->temporaryStrong('container');
return $this->b;
}
}
class b {
public readonly c $c;
use weakObjReference;
function __construct(a $container) {
$this->weakReference($container, 'container'); // $this->container "created"
$this->c = new c($this);
}
function heehee(): mixed {
return $this->c;
}
}
class c {
use weakObjReference;
function __construct(b $container) {
$this->weakReference($container, 'container'); // $this->container "created"
}
function haahaa($name): mixed {
$x = $name . ', '. $this->container->container->name;
$this->container->weakAgain('container');
return $x;
}
}
$a = new a('world 1');
var_dump($a->hoohoo()->heehee()->haahaa('hello')); // EXAMPLE 1
var_dump((new a('world 2'))->hoohoo()->heehee()->haahaa('good afternoon')); // EXAMPLE 2.
Это работает, но очевидно, что это не практическое/структурное решение с ->temporaryStrong () и ->weakAgain() разбросаны по всей системе.
Это кажется нишевой ситуацией, поскольку она возникает только тогда, когда вы создаете экземпляр на муха. Однако в моем случае это довольно стандартно (заводское). И еще с несколькими разными классами.
Как я могу решить эту проблему изящно, не заставляя использовать переменную в пользовательской области?
Подробнее здесь: https://stackoverflow.com/questions/791 ... uses-error
Мобильная версия