2010-06-08 83 views
7

我正在寫一些小幫手類來處理樹木。基本上,我有一個節點和一個代表樹的特殊根節點。我想保持它的通用性和簡單性。這是部分代碼:受保護的構造函數是否被認爲是良好的實踐?

<?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::addById()創建TreeNode實例?
  • 如果是這樣,將TreeNode::__construct()聲明爲private/protected是否是好習慣?

回答

3

我認爲在某些情況下,控制對象的構造並隱藏公共構造函數是有意義的。

這是你的代碼的真實情況:它對於Tree類來控制孩子TreeNode的創建和初始化很有用,因爲它需要控制樹層次結構中添加節點的位置。

如果這些類之間的關係是這樣的,那麼對對象的構造進行控制就顯得尤爲重要,因爲它們之間有關於另一個的信息。

例如:如果稍微更改了您的實現並允許Tree類管理樹中所有節點的節點ID(您可以將這些節點ID存儲在Tree類中的一個數組中)。在這種情況下,如果Tree控制TreeNode是如何創建和初始化的,並且通過Tree類中的方法來完成此操作,那將非常有吸引力。

1
  • 它是明智的強制通過TreeNode::addById()創建TreeNode實例?
  • 如果是這樣,將TreeNode::__construct()聲明爲private/protected是否是好習慣?

如果要強制TreeNode通過TreeNode::addById()創建,則只有明智的路徑是使TreeNode::__construct()私人或受保護(均會在這種情況下工作,但private很可能是因爲它更好會強制子類使用::addChildById)。

至於是否通過TreeNode::addById()創建TreeNode實例是明智的:也就是說,替代方法是將TreeNode::addById()的邏輯傳輸給構造函數。儘管在這種情況下可能,工廠方法通常更通用。

但是請注意,這像現在,由於調用父構造函數沒有被創建Tree對象在PHP需要,可以創造(的亞型)TreeNode對象。您應該考慮在Tree中添加一個私有構造函數以避免實例化。

更正:雖然在PHP中不需要調用父構造函數是事實,但如果在子類中沒有指定構造函數,那麼對父構造函數隱式調用也是正確的;就像現在一樣,PHP會嘗試調用TreeNode的父構造函數,並在直接實例化Tree對象時失敗。

相關問題