2012-01-17 72 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

相关问题