zoukankan      html  css  js  c++  java
  • php对象外访问私有属性,魔术方法__set(),__get(),__isset(),__unset()

      php面向对象编程中是禁止在对象外直接访问由private所定义的私有属性,但是在类中添加魔术方法__set(),__get(),__isset(),__unset()后可间接访问对象中的私有属性,为什么不直接定义为public访问属性呢?这样的好处是可以在魔术方法中定义一些规则,过滤对象外的一些非法数据,比如说一个人的年龄不可能是600岁,人的性别不可能是“苹果”、“石头”之类等等。

    <?php
    class Person{
        private $name;
        private $sex;
        private $age;
        
        /**
          php的构造方法是不能重写的,因为一个类中方法名只能是唯一且不重复的,
          在构造方法中对参数设置初值,相当于其它语言的构造方法重写。
        */
        function __construct($name = '小可爱', $sex = '男', $age = 3){
            $this->name = $name;
            $this->sex = $sex;
            $this->age = $age;
        }
        
        /**
          魔术方法:__set(属性名, 属性值)
        */
        public function __set($propertyName, $propertyValue){
            if($propertyName == 'sex'){
                if(!($propertyValue == '男' || $propertyValue == '女'))
                    return;
            }
            
            if($propertyName == 'age'){
                if($propertyValue < 1 || $propertyValue > 120)
                    return;
            }
                
            $this->$propertyName = $propertyValue;
        }
        
        /**
            魔术方法:__get(属性名)
        */
        public function __get($propertyName){
            if($propertyName == 'sex')
                return '保密';
                
            if($propertyName == 'age'){
                if($this->age > 30)
                    return $this->age - 6;
            }
            
            return $this->$propertyName;
        }
        
        /**
            魔术方法:__isset(属性名)
        */
        public function __isset($propertyName){
            if($propertyName == 'name')
                return false;
                
            return isset($this->$propertyName);
        }
        
        /**
            魔术方法:__unset(属性名)
        */
        public function __unset($propertyName){
            if($propertyName == 'name')
                return;
                
            unset($this->$propertyName);
        }
        
        public function say(){
             echo '姓名:' . $this->name . ',性别:' . $this->sex . ',年龄:' . $this->age . '<br>';
        }
    }
    
    //实列化并且初始化对象
    //$person = new Person;
    $person = new Person('孙悟空', '男', 580);
    echo "<strong style="color:#789">初始化私有属性</strong><br>";
    $person->say();
    
    //在对象外给对象内的私有属性赋值
    //魔术方法 __set() 的使用
    $person->name = '孙晓雨';
    $person->sex = '女';
    $person->age = 32;
    
    echo "<br><strong style="color:#789">__set()修改私有属性</strong><br>";
    $person->say();
    
    echo "<br><strong style="color:#789">__get()获取私有属性</strong><br>";
    
    //在对象外获取对象中的私有属性
    //魔术方法 __get() 的使用
    echo "姓名:" . $person->name . ",性别:" . $person->sex . ",年龄:" . $person->age;
    
    echo "<hr>";
    
    //魔术方法 __isset() 的使用
    var_dump(isset($person->name));
    var_dump(isset($person->sex));
    var_dump(isset($person->age));
    
    echo "<hr>";
    
    //魔术方法 __unset() 的使用
    unset($person->name);
    unset($person->sex);
    unset($person->age);
    var_dump(isset($person->name));
    var_dump(isset($person->sex));
    var_dump(isset($person->age));
    echo "<br>";
    $person->say();

    代码执行后的效果:

      这里有一个小细节,可能是php版本的原因,有的版本在调用属性时,如果没有属性,不会调用魔术方法__get(),上面执行后的最后一行应该是:

      姓名:孙晓雨,性别:,年龄:

    但是我用的版本在调用属性时,如果没有属性就调用了魔术方法__get(),这给代码在不同版本迁移时带来难度。

  • 相关阅读:
    概率期望训练之五
    概率期望训练之四
    JavaScript Source Map详解
    JSON.parse、JSON.stringify
    Linux cp命令直接覆盖不提示方法
    Service Worker
    HTML5 应用程序缓存
    二分图
    Tarjan
    FFT迭代加深 & NTT 多项式求逆
  • 原文地址:https://www.cnblogs.com/qingsong/p/12992930.html
Copyright © 2011-2022 走看看