2010-06-08 16 views
7

Piszę kilka małych klas pomocniczych do obsługi drzew. Zasadniczo mam węzeł i specjalny węzeł główny, który reprezentuje drzewo. Chcę zachować to ogólne i proste. Jest to część kodu:Czy chronieni konstruktorzy uważani są za dobrą praktykę?

<?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); 

?> 

Moje pytania:

  • Czy to rozsądne, aby zmusić TreeNode przypadki, które mają być utworzone przez TreeNode::addById()?
  • Jeśli tak, czy dobrze byłoby ogłosić, że TreeNode::__construct() jest prywatny/chroniony?

Odpowiedz

3

Myślę, że w niektórych przypadkach sensowne jest kontrolowanie budowy obiektów i ukrywanie publicznego konstruktora.

Jest to zgodne z kodem: jest użyteczne dla klasy Tree do sterowania tworzeniem i inicjowaniem jej potomnych TreeNode, ponieważ musi kontrolować położenie węzłów w hierarchii drzewa.

Posiadanie tej kontroli nad budową obiektu jest szczególnie ważne, jeśli relacja między klasami jest taka, że ​​jedna zawiera informacje na temat drugiej.

Na przykład: jeśli nieznacznie zmieniłeś implementację i zezwoliłeś klasie Tree zarządzać identyfikatorami węzłów dla wszystkich węzłów w drzewie (możesz przechowywać je w tablicy w klasie Tree). W tym przypadku byłoby bardzo ważne, aby mieć Tree kontrolę nad tworzeniem i inicjalizowaniem s, a robienie tego za pomocą metody z klasy Tree ma doskonały sens.

1
  • Czy to rozsądne, aby zmusić TreeNode instancje być utworzone przez TreeNode::addById()?
  • Jeśli tak, czy dobrze byłoby ogłosić, że TreeNode::__construct() jest prywatny/chroniony?

Jeśli chcesz zmusić TreeNode być tworzone przez TreeNode::addById() The tylko rozsądna ścieżka jest, aby TreeNode::__construct() prywatne lub chronione (zarówno będzie działać w tym przypadku, ale private prawdopodobnie byłby lepszy od niego zmusiłoby podklasy do użycia ::addChildById).

Co do sensownego wymuszania utworzenia instancji TreeNode przez TreeNode::addById(): alternatywą byłoby przeniesienie logiki TreeNode::addById() do konstruktora. O ile możliwe w tym przypadku, metody fabryczne są na ogół bardziej wszechstronne.

Należy jednak pamiętać, że jak to jest teraz, a ponieważ wywołanie konstruktorów rodzic nie jest wymagane w PHP, ty mogą tworzyć (podtypu) TreeNode przedmiotów poprzez tworzenie Tree obiektów. Należy rozważyć dodanie prywatnego konstruktora do Tree, aby uniknąć tworzenia instancji.

Korekta: chociaż prawdą jest, że wywoływanie konstruktorów macierzystych nie jest wymagane w PHP, jest również prawdą, że istnieje niejawne wywołanie konstruktora macierzystego, jeśli w podklasie nie podano żadnego konstruktora; tak jak jest teraz, PHP spróbuje zadzwonić do konstruktora nadrzędnego TreeNode i nie powiedzie się, gdy bezpośrednio będzie instancją obiektu Tree.

Powiązane problemy