【PHP 面向对象】面向对象(OOP)编程之魔术方法实现重载知识点归纳总结(三)

魔术方法实现重载

    • PHP 通过魔术方法实现重载
      • 属性重载(属性拦截器)
      • 方法重载(方法拦截器)
      • 事件委托(方法重定向)
      • 实战案例(查询构造器)
    • trait: 类功能横向扩展

PHP 通过魔术方法实现重载

魔术方法 作用
__construct() 实例化类时自动调用(构造函数)
__destruct() 类对象使用结束时自动调用(析构函数)
__set() 在给未定义的属性赋值时自动调用
__get() 调用未定义的属性时自动调用
__isset() 使用 isset() 或 empty() 函数时自动调用
__unset() 使用 unset() 时自动调用
__sleep() 使用 serialize 序列化时自动调用
__wakeup() 使用 unserialize 反序列化时自动调用
__call() 调用一个不存在的方法时自动调用
__callStatic() 调用一个不存在的静态方法时自动调用
__toString() 把对象转换成字符串时自动调用
__invoke() 当尝试把对象当方法调用时自动调用
__set_state() 当使用 var_export() 函数时自动调用,接受一个数组参数
__clone() 当使用 clone 复制一个对象时自动调用(克隆)
__debugInfo() 使用 var_dump() 打印对象信息时自动调用

注意: 这些魔术方法的参数都不能通过引用传递。

  • 在给不可访问属性赋值时,__set() 会被调用。
  • 读取不可访问属性的值时,__get() 会被调用。
  • 当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。
  • 当对不可访问属性调用 unset() 时,__unset() 会被调用。

属性重载(属性拦截器)

PHP所提供的 重载(overloading)是指动态地创建类属性和方法。我们是通过魔术方法(magic methods)来实现的。

当调用当前环境下不可访问(未定义或不可见)的类属性或方法时,重载方法会被调用。

● 属性的重载 __get__set

● 方法的重载 __call__callStatic

  
// PHP 重载
class Credit{
   
    private $idNum;
    private $age;
    
    // 魔术方法 构造函数 如果我没有显示的定义__construct方法时候,系统在实例化对象的时候会自动初始一个无参的构造函数
    public function __construct($idNum,$age){
   
        $this->idNum = $idNum;
        $this->age = $age;
    }

    // 我们也可以显示的声明重载方法 __get __set
    public function __set($name,$value){
   
    	echo "Setting $name to $value
"
; $this->$name = $value; return $this->$name; } public function __get($name){ return $this->$name; } } $c = new Credit('341226186915868525',88); // 访问未定义的成员属性时,重载方法会被调用 $c->name = 'zhang'; // __set echo $c->name; // __get // 访问私有成员属性 echo "
"
; $c->idNum = "****************"; echo $c->idNum; ?>

导出问题:因为魔术方法都是公有的,所以一些私有成员的不可见性就不会生效。

解决这一问题,我们需要用到属性重载处理(属性拦截器)

  • __set()当给不可访问的属性赋值的时候会触发

    有两个参数第一个参数是成员名第二个参数是成员的值

  • __get()当读取不可访问的属性的时候会触发
    有一个参数是成员名

// 其中不可访问成员指的是:没有定义的成员,还有因为受到访问控制而访问不到的
  
// PHP 重载
class Credit{
   
    private $idNum;
    private $age;
    
    public function __construct($idNum,$age){
   
        $this->idNum = $idNum;
        $this->age = $age;
    }

    // 设置 中转站
    public function __set($name,$value){
   
    	// 根据属性名称$name 生成对应的属性访问私有接口
        // 'set'.'IdNum' = setIdNum
        $method = 'set'.ucfirst($name);
        // method_exists() 检测对象中是否存在某个方法
        return method_exists($this,$method)?$this->$method($name,$value):null;
    }
    private function setIdNum($name,$value){
   
    	// property_exists()检测对象中是否存在某个属性
        if(property_exists($this,$name)){
   
        	return $this->$name = strlen($value)==18?$value:null;
        }
    }
    private function setAge($name,$value){
   
    	if(property_exists($this,$name) && intval($value)>0){
   
        	return $this->$name = $value;
        }else{
   
        	return $this->$name = null;
        }
    }
    
    // 访问 中转站
    public function __get($name){
   
    	$method = 'get'.ucfirst($name);
         return method_exists($this,$method)?$this->$method($name):null;
    }
    private function getIdNum($name){
   
    	// 用户修改并查看的属性是否存在,并且属性内容已修改成功,不为空。
        if(property_exists($this,$name) && !empty($this->$name)){
   
        	return substr_replace($this->$name,"****",-4,4);
        }else{
   
        	return "身份证信息不合法";
        }
    }
    private function getAge($name){
   
    	if(property_exists($this,$name) && !empty($this->$name)){
   
    		if($this->$name<18){
   
    			return "年龄小于18岁"

你可能感兴趣的:(PHP,php,面向对象,魔术方法,重载)