Ответ 1
Нет способа вызвать
$parent->test = "hello world!";
$parent->child = new B();
и автоматически ссылается на $parent в B.
Как правило, существует четыре способа структурирования ваших классов:
1. Совокупность родительского объекта через Injection, например
class B
{
private $parent;
public function __construct($parent)
{
$this->parent = $parent;
}
public function setParent($parent)
{
$this->parent = $parent;
}
public function accessParent()
{
$this->parent->someMethodInParent();
}
}
Использовать инъекцию конструктора, когда объект должен иметь родителя при его создании. Это отношение has-a, и оно создает очень свободную связь. В B нет закодированных зависимостей, поэтому вы можете легко заменить экземпляр родителя, например, с помощью Mock при UnitTesting. Использование Dependency Injection сделает ваш код более удобным.
В вашем UseCase вы передадите $parent
в B при создании B:
$parent->child = new B($parent);
2. Использовать композицию
class B
{
private $parent;
public function __construct()
{
$this->parent = new Parent;
}
public function accessParent()
{
$this->parent->someMethodInParent();
}
}
Это также отношение has-a, но сопрягает класс Parent с B. Это также не существующий родительский экземпляр, а новый экземпляр. Из формулировки я считаю несколько странным иметь родителя, созданного ребенком. Используйте это, когда зависимость - это класс, который не считается существующим вне корневого класса, но является частью всего, что он представляет.
Для вашего UseCase нет способа сделать $parent->child = new B();
и знать, что такое родитель при использовании этого подхода, если только $parent не является Singleton. Если это так, вы можете получить экземпляр Singleton, например. Parent::getInstance()
, чтобы добиться того, чего вы хотите, но обратите внимание, что Singletons - это не все любимые шаблоны, например. трудно проверить.
3. Использовать наследование
class B extends Parent
{
public function accessParent()
{
$this->someMethodInParent();
}
}
Таким образом вы создаете отношения is-a. Все общедоступные и защищенные методы и свойства из класса Parent (но не определенного экземпляра) будут доступны в B, и вы можете получить к ним доступ через ключевое слово $this
экземпляра B.
Для вашего UseCase этот подход не работает, так как вам не обязательно иметь экземпляр родителя вообще, но B будет инкапсулировать все родительское, когда оно создаст
$b = new B;
4. Использовать глобальное ключевое слово
class B extends Parent
{
private $parent;
public function __construct()
{
global $parent;
$this->parent = $parent;
}
public function accessParent()
{
$this->parent->someMethodInParent();
}
}
Ключевое слово global
импортирует глобальные переменные в текущую область. В общем случае вам следует избегать использования глобального ключевого слова в контексте OO, но используйте один из трех других методов выше, предпочтительно первый. В то время как это была языковая функция, она нахмурилась - хотя это будет следующая ближайшая вещь к первой, например.
$parent->child = new B();
В любом случае, надеюсь, что это поможет.