繁体   English   中英

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

[英]PHP Abstract ; Is this the right way to use an 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);
        }
    }

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

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

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

一点建议:

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM