PHP摘要;这是使用抽象类的正确方法吗?

时间:2012-01-17 04:22:37

标签: php oop abstract-class

我只是想知道我是否走在正确的道路上。使大多数函数抽象似乎没有必要,因为数据几乎相同。这是一种无效的方法吗?

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

所有这一切都是打印出具有特定查询的任务,并返回一个关联数组。

3 个答案:

答案 0 :(得分:2)

“这是一种无效的方法吗?”

没有。您的代码正确使用抽象。您可以集中共同的逻辑,但是通过将父类声明为抽象,您正在强制通过子类(扩展您的抽象,父类)来完成类的实例化,这很有效。

建议:

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

以这种方式声明成员变量会破坏封装。我建议你通过调用代码分配这样的成员变量,而不是在构造函数中。

答案 1 :(得分:0)

从抽象类继承时,父类声明中标记为abstract的所有方法都必须由子类定义;此外,必须使用相同(或限制较少)的可见性来定义这些方法。例如,如果将抽象方法定义为protected,则必须将函数实现定义为protected或public,而不是private。此外,方法的签名必须匹配,即类型提示和所需参数的数量必须相同。 这也适用于PHP 5.4中的构造函数。在5.4构造函数签名可能不同之前。 - php.net

在您的实现中,构造函数的签名是不同的..

答案 2 :(得分:0)

这是一个使用抽象类的时间的真实例子:小部件。

我有一个小部件模型,它具有创建,编辑,保存或呈现小部件所需的大部分功能。但是,有两个基本指标我需要这个类是抽象的:

  1. 每个小部件实现必须定义edit()方法和render()方法,因为照片小部件具有不同的属性,并且应该与推文小部件显示不同。
  2. 我不需要“普通”Widget实例。它必须始终是该类的子实现。