Дерево объектов. child-parent задачка.

NOX

Новичок
Дерево объектов. child-parent задачка.

Есть дерево, к примеру, из 3х объектов
PHP:
$obj1, $obj2, $obj3
Как добратся (пупутно собирая информацию нп. названия классов) до основы ($obj1) этого дерева из $obj3
PHP:
$obj1->$obj2->$obj3;
причем требуется возможность иметь пройти до основы из любого элемента дерева и получить в нём вышеупоминаемый список названий классов.


В голову приходит только что-то вроде (это примерно, проилюстрировать общюю идею)
PHP:
$obj2->parent = &$obj1;
$obj3->parent = &$obj2;

$tmp = $this->parent;

while(isset($tmp)){
  $tmp = $tmp->parent;
  data[] = get_class($tmp);
}
 

AmdY

Пью пиво
Команда форума
берёшь класс, затем get_object_vars, пробегаешься по всему и ищешь обьекты, берёшь имя класса и аттрибуты и так дальше
 

NOX

Новичок
Автор оригинала: AmdY
берёшь класс, затем get_object_vars, пробегаешься по всему и ищешь обьекты, берёшь имя класса и аттрибуты и так дальше
Видимо кто-то из нас что-то недопонял.
Постараюсь переформулировать: каким образом сделать так, что бы $obj3 знал, что он наследник (не наследует, а наследник исходя из иерархии дерева) $obj2, а $obj2 - наследник $obj1.
 

dr-sm

Новичок
Re: Дерево объектов. child-parent задачка.

Автор оригинала: NOX
Есть дерево, к примеру, из 3х объектов
PHP:
$obj1, $obj2, $obj3
Как добратся (пупутно собирая информацию нп. названия классов) до основы ($obj1) этого дерева из $obj3
PHP:
$obj1->$obj2->$obj3;
причем требуется возможность иметь пройти до основы из любого элемента дерева и получить в нём вышеупоминаемый список названий классов.
добираться, попутно собирая информацию, круче всего паттерном visitor )
 

weregod

unserializer
Class/Object Functions
-----------------------------

PHP 4, PHP 5

string get_parent_class ( [mixed object] )

Retrieves the parent class name for object or class.


Parameters

object
The tested object or class name


мануалы никак читать не получается ?
 

AmdY

Пью пиво
Команда форума
weregod ты не прав, это не то что нужно.
а вообще-то, учитывая что в рнр5 $obj2->parent = $obj1, без паттерна не обойтись :(
 

weregod

unserializer
термин "наследник" в отношении классов и объектов подразумевает именно то, что я имел ввиду

термина "инкапсуляция" на момент поста в ветке не вижу
 

AmdY

Пью пиво
Команда форума
по терминологии ты прав, но задача явно в другом. челу нужно получить иерархию обектов

а учитывая что может быть как $obj1->$obj2->$obj3 так и $obj1->$obj2->$obj3->$obj2, задача решается с помощью визитёра.
 

Fred

Новичок
Сделать композитный объект

PHP:
class TreeElement {
    /**
    * @var TreeElement
    */
    private $parent;

    public function getParent() {
        return $this->parent;
    }

    public function setParent(TreeElement $parent) {
        $this->parent = $parent;
    }
}
а потом использовать

PHP:
$obj1 = new TreeElement();
$obj2 = new TreeElement();
$obj2->setParent($obj1);
$obj3 = new TreeElement();
$obj3->setParent($obj2);
И теперь верхнего родителя можно получить

PHP:
$parent = $obj3->getParent()->getParent();
ну или в while, если не знаешь, сколько все родителей сверху в иерархии

PHP:
function getTopParent(TreeElement $obj) {
    while (true) {
        $parent = $obj->getParent();
        if (! $parent instanceof TreeElement) {
            return $obj;
        }
        $obj = $parent;
    }
}
 

AmdY

Пью пиво
Команда форума
кстати, по теме http://ru.wikipedia.org/wiki/Диаграмма_классов
 

NOX

Новичок
всем спасибо
weregod, извини за терминологию, не придумал других слов. Что бы писать "а недосуг почитать", должно быть недосуг самому это сделать.
Fred, как раз это я предложил в первом посте.
visitor паттерн учту.
Интересуюсь нет ли других идей.
 

dr-sm

Новичок
zerkms, в GoF есть пример по поводу Composite + Visitor.
Вот, код конечно надуманный, но общую идею показывает :D :
PHP:
interface visitor {
	public function visitRootNode($node);
	public function visitLeafNode($node);
}

interface node {
	public function accept(visitor $v);
	public function getName();
}

class rootNode implements node {
	public function accept(visitor $v) {
		$v->visitRootNode($this);
	}
	public function getName() {
		return 'Root';
	}
}

class leafNode implements node {
	private $name;
	private $parent;
	public function __construct($name, $parent) {
		$this->name = $name;
		$this->parent = $parent;
	}
	public function accept(visitor $v) {
		if ($v->visitLeafNode($this)) {
			$this->getParent()->accept($v);
		}
	}
	public function getName() {
		return $this->name;
	}
	public function getParent() {
		return $this->parent;
	}
	public function setParent($parent) {
		$this->parent = $parent;
	}
}

class treeChecker implements visitor {
	private $path = array();
	public function reset() {
		$this->path = array();
	}
	public function visitRootNode($node) {
		$this->echoPath('Tree is ok', $node->getName());
		return true; 
	}
	public function visitLeafNode($node) {
		if ($this->inPath($node)) {
			$this->echoPath('Loop detected', $node->getName());
			return false;
		}
		$this->path[] = $node;
		if (!$node->getParent()) {
			$this->echoPath('Dangling leaf reference', '?');
			return false;
		}
		return true;
	}
	private function echoPath($message, $start) {
		echo $message . ': <b>' . $start . '</b>';
		for ($i = count($this->path) - 1; $i >= 0; --$i) {
			echo ' -> ' . $this->path[$i]->getName();
		}
		echo '<br/>';
	}
	private function inPath($node) {
		for ($i = count($this->path) - 1; $i >= 0; --$i) {
			if ($this->path[$i] === $node) {
				return true;			
			}		
		}
		return false;
	}
}

$trch = new treeChecker();
$tree = new leafNode('zzz', new leafNode('yyy', new leafNode('xxx', new rootNode())));
$tree->accept($trch);
$trch->reset();

$tree1 = new leafNode('aaa', new leafNode('bbb', new leafNode('ccc', null)));
$tree1->accept($trch);
$trch->reset();

$loop = new leafNode('loop', null);
$loop->setParent(new leafNode('mmm', new leafNode('lll', new leafNode('kkk', $loop))));
$loop->accept($trch);
-~{}~ 10.03.08 11:08:

также, хочу отметить, что ты NOX, своим деревом, запарил не только меня, но и остальных участников форума.
структура:
PHP:
class element {
	private $parent;
	public function getParent() {
		return $this->parent;
	}
    public function setParent(element $parent) {
		$this->parent = $parent;
	}
}
это не дерево, это односвязный список, и соотвецтвенно composite тут никак не катит ).
 

NOX

Новичок
dr-sm, спасибо за пример. Твоего пасажа насчёт запарки не понял - никто ж не заставляет.
_Очень_ приблизительно мой нод сейчас выглядит так
PHP:
class Node { 
    
    private $childs = array(); 

    public function getChild($name) { 
        return $this->childs[$name]; 
    } 
    public function getChild($obj) { 
        $this->childs[] = $obj; 
    } 
}
 

dr-sm

Новичок
понятно, вот это дерево, те composite. по нему можно двигацо только в прямом направлении, те от корня.
для решения твоей задчи обратного прохода, его надо скрестить с односвязным списком.
это я и имел ввиду в своем пассаже :D
 
Сверху