美文网首页PHP实战PHP经验分享
PHP反思:__get() /__set()实现类属性

PHP反思:__get() /__set()实现类属性

作者: codefine | 来源:发表于2018-02-08 16:08 被阅读12次

    先贴代码

    <?php
    
    class InvalidCallException extends \Exception  {}
    class UnknownPropertyException extends \Exception {}
    
    /**
     * 定义一个对象类
     * 实现__get()
     * 实现__set()
     * 赋予一个对象属性读写的能力
     */
    abstract class Object
    {   
        public function __get($key)
        {   
            $method_name = 'get' . $key;
            if (method_exists($this, $method_name)) {
                return call_user_func([$this, $method_name]);
            } else if (method_exists($this, 'set' . $key)) {
                throw new \InvalidCallException("属性是只写的:" . __class__ . '::' . $key);
            } else {
                throw new \UnknownPropertyException("属性不存在:" . __class__ . '::' . $key);
            }
        }
    
        public function __set($key, $value)
        {   
            $method_name = 'set' . $key;
            if (method_exists($this, $method_name)) {
                return call_user_func([$this, $method_name], $value);
            } else if (method_exists($this, 'get' . $key)) {
                throw new \InvalidCallException("属性是只读的:"  . __class__ . '::' . $key);
            } else {
                throw new \UnknownPropertyException("属性不存在:" . __class__ . '::' . $key);
            }
        }
    }
    
    
    /**
     * Article类
     * title属性,可读写
     * author属性,只读
     * 内部定义私有成员,对外不可见,实现封装
     * 定义getter,setter,设置属性读写,实现封装
     */
    class Article extends Object
    {
    
        private $_title;
        private $_author = 'codefine';
        private $_content;
    
        public function getTitle()
        {
            return $this->_title;
        }
    
        public function setTitle($title)
        {
            $this->_title = trim($title);
        }
    
        public function getAuthor()
        {
            return $this->_author;
        }
    
        public function setContent($value)
        {
            $this->_content = $value;
            var_dump($this->_content);
        }
    }
    
    $obj = new Article();
    
    //title 支持读写
    $obj->title = '__get __set的使用';
    var_dump($obj->title);
    
    //只读
    // $obj->author = '修改作者'; //Fatal error: Uncaught InvalidCallException: 属性是只读的:Object::author
    var_dump($obj->author);
    
    //只写
    $obj->content = '内容属性赋值';
    // var_dump($obj->content); // Fatal error: Uncaught InvalidCallException: 属性是只写的:Object::content 
    
    

    总结

    通过代码示例,可以发现,PHP中的类,本身没有设计getter, setter。但提供了__get() / __set()魔术方法,在访问(设置)不存在的类成员的时候,提供回调处理。

    通过__get() / __set() 魔术方法,交由程序员自己发挥想象,自行定制实现规则,既可以实现成员的类型限制,也可以实现统一包装,格式化,访问控制等等功能。

    相关文章

      网友评论

        本文标题:PHP反思:__get() /__set()实现类属性

        本文链接:https://www.haomeiwen.com/subject/fnmttftx.html