【问题标题】:Get constant overridden from child in method declared within an abstract class在抽象类中声明的方法中从子类中获取常量覆盖
【发布时间】:2011-11-02 22:33:18
【问题描述】:

我有这个(缩短):

abstract class MyModel
{
    const DBID = "";
    const TOKEN = "";

    public function getDB()
    {
        if(!$this->_DB)
        {
            $c = get_called_class(); // doesn't work pre php 5.3
            echo $c::DBID; // doesn't work pre php 5.3
            echo $c::TOKEN // doesn't work pre php 5.3
        }

        return $this->_qb;
    } 

问题是get_called_class() 和 $c::DBID/TOKEN 在 php 中不起作用

有没有一种方法可以在与 5.2.9 兼容的抽象类中完成相同的任务?

【问题讨论】:

    标签: php oop class reflection constants


    【解决方案1】:

    编辑: 常量并不是真的要在整个对象实例化过程中更改,您可能需要考虑使用成员变量。

    抽象类不能直接实例化。您可以创建一个子类来扩展您的抽象类,然后调用 getDb()。

    abstract class MyModel
    {
        private $dbId;
        private $token;
    
        public function setDbId($dbId)
        {
            $this->dbId = $dbId;
        }
    
        public function setToken($token)
        {
            $this->token = $token;
        }
    
        public function getDbId()
        {
            return $this->dbId;
        }
    
        public function getToken()
        {
            return $this->token;
        }
    
        public function __construct()
        {
            // All child classes will have the same values
            $this->setDbId('myParentDbId');
            $this->setToken('myParentToken');
        }
    
        protected function getDb()
        {
            echo $this->getDbId();
            echo $this->getToken();
        }
    }
    
    class MyChildModel extends MyModel
    {
        // Don't need any methods, just access to abstract parent
        // But if I wanted to override my parent I could do this
        public function __construct()
        {            
            parent::__construct();
    
            $this->setDbId('myChildDbId');
            $this->setToken('myChildToken');
        }
    }
    
    $myChildModel = new MyChildModel();
    var_dump($myChildModel->getDb());
    

    【讨论】:

    • 在抽象构造函数中,我不会这样做:$this->setDbId(parent::$dbID) 和 $this->setToken(parent::$token)?
    • 如果您想使用相同值的父母版本,只需取出孩子的覆盖值,然后对 getDb() 的任何调用都将使用父母版本。我只是向您展示了此解决方案提供的灵活性。
    【解决方案2】:

    我在 PHP 5.2 代码库中有一个解决方案,它使用反射从超类中获取子类的常量,但我建议不要这样做,除非绝对必要,因为反射是 PHP 中相对昂贵的工具的表现。

    PHP 5.3 在 static::CONST 中引入了 static 关键字,而不是 self::CONST 来访问类的静态成员。我从未真正尝试过它,但我相信它应该能够满足您的需求。在 PHP 手册中查找后期静态绑定。

    为了记录,这里是使用反射获取子类常量的方法的代码。

    class SomeClass
    {
        /**
         * Get reflection class for item
         * 
         * Get a reflector for this item so that internal constants can be used for the permission checking
         * functions.  This is necessary because of how static binding works prior to PHP 5.3.  
         * 
         * @return ReflectionClass
         */
        protected function getRef ()
        {
            if (!$this -> ref)
            {
                $this -> ref    = new ReflectionClass ($this);
            }
            return ($this -> ref);
        }
    
        /**
         * Check that the user has permission to create an item of the type this object represents
         *
         * @todo Use late static binding instead of reflection once PHP 5.3 becomes available on the server
         * @return bool True if OK
         */
        public function canCreate ()
        {
            $ref    = $this -> getRef ();
            if ($flag = $ref -> getConstant ('USR_FLAG_CREATE'))
            {
                return (self::$user -> permissions [$flag]);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-25
      • 2020-02-15
      • 1970-01-01
      • 1970-01-01
      • 2016-05-10
      • 1970-01-01
      相关资源
      最近更新 更多