Я пишу некоторые небольшие классы помощника для обработки деревьев. В основном у меня есть узел и специальный корневой узел, который представляет дерево. Я хочу сохранить это универсальным и простым. Это - часть кода:
<?php
class Tree extends TreeNode{
public function addById($node_id, $parent_id, $generic_content){
if( $parent = $this->findNodeById($parent_id) ){
$parent->addChildById($node_id, $generic_content);
}
}
}
class TreeNode{
public function __construct($node_id, $parent_id, $generic_content){
// ...
}
protected function addChildById($node_id, $generic_content){
$this->children[] = new TreeNode($this->node_id, $node_id, $generic_content);
}
}
$Categories = new Tree;
$Categories->addById(1, NULL, $foo);
$Categories->addById(2, NULL, $bar);
$Categories->addById(3, 1, $gee);
?>
Мои вопросы:
TreeNode
экземпляры, которые будут созданы через TreeNode::addById()
?TreeNode::__construct()
как частный/защищающий?Я думаю, что в некоторых случаях имеет смысл контролировать построение объектов и скрывать публичный конструктор.
Это относится к вашему коду: классу Tree
полезно контролировать создание и инициализацию его дочерних TreeNode
, потому что ему нужно контролировать, куда добавляются узлы в иерархии дерева.
Наличие такого контроля над созданием объектов особенно важно, если отношения между классами таковы, что один имеет информацию о другом.
Например: если вы немного измените свою реализацию и позволите классу Tree
управлять идентификаторами узлов для всех узлов дерева (вы можете хранить их в массиве внутри класса Tree
). В этом случае было бы очень убедительно, если бы Tree
контролировал, как создаются и инициализируются TreeNode
ы, и делать это через метод класса Tree
вполне логично.
- Разумно ли принудительно создавать экземпляры
TreeNode
с помощьюTreeNode :: addById ()
?- Если это так, было бы хорошей практикой объявить
TreeNode :: __ construct ()
как закрытый / защищенный?
Если вы хотите принудительно создать TreeNode
через TreeNode :: addById ()
, только разумный путь - сделать TreeNode :: __ construct ()
закрытым или защищенным (оба будут работать в этом случае, но закрытый
, вероятно, будет лучше, поскольку это заставит подклассы для использования :: addChildById
).
Что касается целесообразности принудительного создания экземпляров TreeNode
с помощью TreeNode :: addById ()
: это так, альтернативой может быть передача TreeNode :: addById ()
в конструктор. Хотя в этом случае возможно, фабричные методы, как правило, более универсальны.
Однако обратите внимание на , что, как сейчас , и поскольку вызов родительских конструкторов не требуется в PHP, вы можете создать (подтип) TreeNode
путем создания объектов Tree
. Вам следует подумать о добавлении частного конструктора в Tree
, чтобы избежать создания экземпляров.
Исправление: хотя верно, что вызов родительских конструкторов не требуется в PHP, также верно и то, что существует неявный вызов родительского конструктора, если конструктор не указан в подклассе; так что сейчас PHP попытается вызвать родительский конструктор TreeNode
и потерпит неудачу при непосредственном создании экземпляра объекта Tree
.