2012-01-17 73 views
0

我只想知道我是否在正確的道路上。由於數據幾乎相同,因此使大部分功能抽象化似乎並不必要。這是一種無效的方法嗎?PHP摘要;這是使用抽象類的正確方法嗎?

<?php 

    abstract class Model_Tasks { 

     /** 
     * Database object 
     * 
     * @access protected 
     */ 
     protected $db; 

     /** 
     * User ID 
     * 
     * @access protected 
     */ 
     protected $uid; 

     /** 
     * Data array 
     * 
     * @access protected 
     */ 
     protected $data; 

     /** 
     * SQL Query 
     * 
     * @access protected 
     */ 
     protected $query; 

     /** 
     * __construct 
     * 
     * @access protected 
     */ 
     protected function __construct($query) { 
      $this->db = Model_DB::getInstance(); 
      $this->uid = $_SESSION['uid']; 

      $this->query = $query; 
      $this->getTasks(); 
     } 

     /** 
     * getTasks 
     * 
     * @param string 
     * @access abstract protected 
     */ 
     protected function getTasks() { 
      $result = $this->db->prepare($this->query); 
      $result->execute(array(
       ':uid' => $this->uid 
      )); 
      $this->data =& $result->fetchAll(); 
      $this->taskCount = $result->rowCount(); 
     } 

     /** 
     * constructTask 
     * 
     * Build the HTML of a task 
     * 
     * @param int 
     * @param int 
     * @param string 
     * @param string 
     * @access protected 
     */ 
     protected function constructTask(
      $id, $cost, $title, $checked = 0 
     ) { 
      $cost = money_format('$%i', $cost); 
      $title = stripslashes($title); 

      return ' 
       <label class="task"> 
        <input type="checkbox" name="done[]" rel="'.$id.'" '.($checked?'checked="checked"':'').' /> 
        <code>'.$cost.'</code> &mdash; '.$title.' 
       </label>'."\n"; 
     } 

     /** 
     * generateOutput 
     * 
     * Call by key [pending, completed] and return the constructed tasks 
     * 
     * @param bool 
     * @access final public 
     */ 
     final public function generateOutput($checked) { 

      try { 
       if(!is_bool($checked)) throw new Exception('generateOutput must contain a boolean variable'); 

       if(!isset($this->data)) throw new Exception('Array has not been set.'); 
       else $data = $this->data; 
      } catch(Exception $e) { 
       die('<pre>'.$e->getMessage().'<hr />'.$e->getTraceAsString()); 
      } 

      if(is_array($data)): foreach($data AS &$r) 
       $str .= $this->constructTask($r['id'], $r['cost'], $r['title'], $checked); 

      else: 
       $str = '<label class="tasks"></label>'; 

      endif; 

      return $str; 
     } 
    } 

    // ------------------------------------------------------------------------ 

    /** 
    * pendingTasks 
    * 
    * @access public 
    */ 
    class pendingTasks extends Model_Tasks { 

     public $taskCount; 

     public function __construct() { 
      $query = ' 
       SELECT id, title, cost 
       FROM tasks 
       WHERE (
        status IS FALSE 
        AND uid = :uid 
       ) ORDER BY cost DESC 
      '; 

      parent::__construct($query); 
     } 
    } 

    /** 
    * completedTasks 
    * 
    * @access public 
    */ 
    class completedTasks extends Model_Tasks { 

     public function __construct() { 
      $query = ' 
       SELECT id, title, cost 
       FROM tasks 
       WHERE (
        status IS TRUE 
        AND uid = :uid 
       ) ORDER BY id DESC 
       LIMIT 7 
      '; 

      parent::__construct($query); 
     } 
    } 

它所做的是打印任務與特定的查詢,並返回一個關聯數組。

+1

如果你沒有任何抽象方法,那麼它真的是「抽象的」呢?您可以通過傳遞查詢直接實例化「Model_Tasks」類... – landons 2012-01-17 04:27:45

+0

Lol的確如此。不過,我只是想抓住這個概念。 – 2012-01-17 04:28:56

+0

哦......我現在明白了。你聲明構造函數是受保護的。這是使它變得抽象的一種奇怪的方式;) – landons 2012-01-17 04:36:42

回答

2

「這是一個無效的方法嗎?」

號您的代碼是否正確使用抽象。你可以集中共同的邏輯,但是通過聲明父類是抽象的,你迫使類的實例化通過一個子類(擴展你的抽象,父類)來完成,這很好地工作。

建議海賊王:以這種方式

$this->uid = $_SESSION['uid']; 

聲明成員變量打破封裝。我建議你通過你的調用代碼來分配成員變量,而不是在你的構造函數中。

0

當從一個抽象類繼承,所有的方法標誌着父類聲明抽象必須由孩子來定義;另外,這些方法必須用相同(或更少限制)的可見性來定義。例如,如果抽象方法被定義爲受保護的,則必須將函數實現定義爲protected或public,但不是私有的。此外,方法的簽名必須匹配,即類型提示和所需參數的數量必須相同。 這也適用於PHP 5.4以上的構造函數。在5.4構造函數簽名之前可能會有所不同。 - php.net

在構造函數中執行的簽名是不同的..

+0

然而,構造函數沒有被聲明爲abstract ... – landons 2012-01-17 04:35:35

+0

有趣不必相同> = 5.4的結構特徵。首次閱讀後,它似乎降低了靈活性。 – 2012-01-17 04:40:12

0

這裏的時候使用抽象類一個真實的例子:小部件。

我有了MOST的創建,編輯,保存,或呈現一個Widget所需功能的窗口小部件模型。不過,也有我需要這個類是抽象的兩個基本指標:

  1. 每個widget實現必須定義一個edit()方法和render()方法,如光部件有不同的屬性,應該從鳴叫的顯示方式不同小部件。
  2. 我有沒有必要爲一個「普通」的Widget實例。它必須始終是班級的一個孩子實施。
+0

對。我仍然在試圖弄清楚這些符合我到目前爲止所做的,但我可以看到可能性。據我所知,這是「按合同編程」 - 對嗎?意思是保持嚴格? – 2012-01-17 04:54:54

+1

@Talasan Nocholson只要不要忘記,你可能並不總是需要一個抽象類。 =) – 2012-01-17 05:08:35

相關問題