Я пытаюсь создать свободный интерфейс для объектов дерева.
Вот упрощенный пример того, что я сейчас делаю:
<?php
class node {
private $childs = array();
private $parent;
public function __construct($parent = null) {
$this->parent = $parent;
}
public function addChild($child) {
$this->childs[] = $child;
return $this;
}
public function createChild() {
return $this->addChild(new node($this));
}
public function setFoo() {
/* do something */
return $this;
}
}
$root = new node();
$root ->addChild((new node($root))
->setFoo()
)->addChild((new node($root))
->setFoo()
);
?>
Я хотел бы уменьшить часть, где я создаю дерево.
Что я хочу сделать, это что-то вроде этого:
$root->createChild()->setFoo();
$root->createChild()->setFoo();
в одну строку. И без необходимости явно создавать новые экземпляры узлов (как я делал в первом коде с new
операторы).
Моя цель — создать любое дерево любого порядка и его узлы любой степени без необходимости ставить точку с запятой в коде.
Вместо того, чтобы добавлять функцию createChild, я думаю, что вы должны изменить свой конструктор и функции addChild, чтобы последовательно установить отношения родитель / потомок в данных. Как только вы это сделаете, функцию addChild и конструктор можно использовать для выполнения того, что вы описали, без функции createChild. Прямо сейчас ваш конструктор позволяет создавать перекрестные связи между различными деревьями и ветвями в деревьях, так что это, вероятно, нужно будет изменить в любом случае.
class node {
private $childs = array();
private $parent;
public function __construct(node $parent = null) {
if(!is_null($parent)) {
$parent->addChild($this);
}
}
public function addChild(node $child) {
$this->childs[] = $child;
$child->parent = $this;
return $this;
}
public function setFoo() {
/* do something */
return $this;
}
}
С этим вы можете связать новые объекты в дерево:
$tree = (new node())->addChild(new node())
->addChild((new node())->setFoo())
->addChild((new node())->addChild(new node())
->addChild(new node())
->setFoo()
);
Попытка использовать функцию createChild — сложная ситуация, когда иногда вам нужен родитель, а иногда ребенок. Вы можете решить это, используя возвращаемый объект, который содержит оба, но я думаю, что лучше избегать такой ситуации. Если вам не нравится синтаксис «(new node ())», статическая функция может быть подходящим вариантом:
public static function create(node $parent = null) {
return new node($parent);
}
Что может быть немного красивее в зависимости от ваших вкусов:
$tree = node::create()->addChild(node::create())
->addChild(node::create()->setFoo())
->addChild(node::create()->addChild(new node())
->addChild(new node())
->setFoo()
);
Вы можете добавить эти методы, чтобы создать как ребенок, как вы можете.
public function createManyChild($nbrOfChild) {
for($i = 0; $i < $nbrOfChild; $i++){
$this->addChild(new node($this));
}
return $this;
}
И используйте такой код.
$root = new node();
$root->createManyChild(3)->setFoo();