PHP面向对象程序设计重载(overloading)操作详解

 更新时间:2019年8月18日 17:55  点击:274

本文实例讲述了PHP面向对象程序设计重载(overloading)操作。分享给大家供大家参考,具体如下:

重载

PHP中的”重载”与其它绝大多数面向对象语言不同,只是他们都是用的相同的名词而已。传统的”重载”是用于提供多个同名的 类方法,但各方法的参数类型和个数不同。 PHP所提供的”重载”(overloading)是指动态地”创建”类属性和方法。当调用当前环境下未定义不可见的类属性或方法时,重载方法会被调用。是通过魔术方法(magic methods)来实现的。

一般来说,把类中的成员属性都定义为private的,这更符合现实的逻辑,能够更好的对类中成员起到保护作用。但是,对成员属性的读取和赋值操作是非常频繁的,而如果在类中为每个私有属性都定义可以在对象的外部获取和赋值的公有方法,又是非常非常烦恼的。因此在PHP5.1.0以后的版本中,预定义了两个方法“__get()”和“__set()”,用来完成对所用私有属性都能获取和赋值操作,以及用来检查私有属性是否存在的方法“__isset()”和用来删除对象中私有属性方法“__unset()”。
通俗一点来说,重载在php中的含义是指,当一个对象或类使用其未定义或不可见的属性和方法时,其中的一些“处理机制”。

属性重载

对一个对象不存在的属性进行使用时,这个类中预先设定好的应对办法(处理机制)。

属性,本质就是变量,其只有4个操作:

取值:

当对一个对象不存在(未定义或不可见)的属性进行“取值”时,就会自动调用方法:__GET()方法不区分大小写。

赋值:

当对一个对象不存在(未定义或不可见)的属性进行“赋值”时,就会自动调用方法:__SET()

判断(isset):

当对一个对象不存在(未定义或不可见)的属性进行isset()判断时,就会自动调用方法:isset()

销毁(unset):

当对一个对象不存在的(未定义或不可见)属性进行unset()判断时,就会自动调用方法:unset()

以上4个方法,被称为魔术方法。

魔术方法

__GET($属性名):

在对一个对象不存在的属性进行“取值”的时候,会自动调用的方法,其中该方法可以带一个形参,表示要对之取值而又不存在的属性名(字符串),可以使用该方法对意外情况进行某种特殊的处理。

例如:

class A{  public $p1 = 1;}
$a1 = new A();
echo $a1->p1; //1
echo $a1->p2; //未定义$p2,会报错, Notice: Undefined property: A::$p2

php的重载,使用__get()方法对上面的出错作“优雅处理”。

class A{  public $p1 = 1;  //
private $p2 = 1; //这里将属性私有化,其实和未定义一样,对外部来说都相当于不存在 
 function __get($prop_name){    
 /*    //比如可以这样处理    
 echo "<br />{$prop_name}属性还未定义(不存在)!";    
 return ""; //也可以返回0,或false等   
  */    
//还可以这样处理    
trigger_error("发生错误:属性不存在!", E_USER_ERROR);    die();  }
}
$a1 = new A();echo $a1->p1; //1
echo $a1->p2; //未定义$p2,但经过"处理"

这里举一个对所用私有属性获取的操作的例子。

例子:

class Person{ 
public $name;  
public $sex;  
private $age; //年龄私有化,类外不能直接访问这个属性  
function __construct($name='', $sex='', $age){    
$this->name = $name;    
$this->sex = $sex;    
$this->age = $age;  
}  
private function __get($propertyName){ //这里要用private修饰,防止类外部调用    
if($propertyName == 'age'){      
return $this->age;   
 }  
}
}
$p = new Person('yeoman', '男',23);
$v1 = $p->name;
$v2 = $p->sex;
$v3 = $p->age;  //自动调用了__get()方法获取私有属性age(函数定义里面返回)
echo "name=$v1, sex=$v2, age=$v3";

运行结果为:

name=yeoman, sex=男, age=23

__SET($属性名, 值):

当对一个对象不存在的属性进行“赋值”时,就会自动调用这个内部的魔术方法;其有2个形参,分别代表要对不存在的属性进行赋值的“属性名”和“属性值”。
这个方法,结合_GET方法,往往可以使我们定义的类,有一种可扩展的特性。即:类或对象的属性,可以更为方便自由。

例子:

class A{  //定义一个属性,  
protected $prop_list = array();  //初始为空数组  
//这个方法会在A的对象使用一个不存在的属性进行赋值时调用  
function __set($p,$v){    //echo "使用不存在的属性!";    
$this->prop_list[$p] = $v;  }  
function __get($p){    return $this->prop_list[$p];  }}
$a1 = new A();$a1->p1 = 1;  
//不存在的属性名赋值,此时会调用_set(),并传过去"p1"和1$a1->p2 = 2;$a1->ac = 'avc';
echo "<br />输出这些“不存在的属性”的值:";
echo "<br />a1->p1:" . $a1->p1;  
//不存在的属性名取值,此时会调用_get(),并传过去"p1"
echo "<br />a1->p2:" . $a1->p2;echo "<br />a1->ac:" . $a1->ac;

运行结果为:

输出这些“不存在的属性”的值:
a1->p1:1
a1->p2:2
a1->ac:avc

__ISSET($属性名):

当对一个对象不存在的属性进行isset()判断时,就会自动调用内部方法:isset();

用法:

$v1 = isset($对象->不存在的属性);  //此时会调用这个对象所属类中的魔术方法:isset()

例子:

class A{  //定义一个属性,  
protected $prop_list = array();  //初始为空数组  
//这个方法会在A的对象使用一个不存在的属性进行赋值时调用  
function __set($p,$v){    //echo "使用不存在的属性!";   
 $this->prop_list[$p] = $v;  }  
 function __get($p){    
 if($this->prop_list[$p]){      
 return $this->prop_list[$p];    
 }else{      return "该属性不存在!";    }  }  
 function __isset($prop){  //__isset()是自定义的方法, isset()是系统函数    
 $re = isset($this->prop_list[$prop]);    return $re;  }}
 $a1 = new A();$a1->p1 = 1;//不存在的属性名赋值,此时会调用_set(),并传过去"p1"和1$a1->p2 = 2;$a1->ac = 'avc';
 echo "<br />输出这些“不存在的属性”的值";
 echo "<br />a1->p1:" . $a1->p1;
 //不存在的属性名取值,此时会调用_get(),并传过去"p1"
 echo "<br />a1->p2:" . $a1->p2;
 echo "<br />a1->ac:" . $a1->ac;//下面演示isset判断不存在的属性
 $v1 = isset($a1->p1); //存在
 $v2 = isset($a1->ppp1);  //不存在var_dump($v1);
 echo "<br />";var_dump($v2);

运行结果:

输出这些“不存在的属性”的值
a1->p1:1
a1->p2:2
a1->ac:avc
boolean true
boolean false

__UNSET($属性名)

当对一个对象不存在的属性进行unset()销毁时,就会自动调用内部方法:unset();

class A{  //定义一个属性, 
protected $prop_list = array();  //初始为空数组  
//这个方法会在A的对象使用一个不存在的属性进行赋值时调用  
function __set($p,$v){    //echo "使用不存在的属性!";    
$this->prop_list[$p] = $v;  }  
function __get($p){    
if($this->prop_list[$p]){     
 return $this->prop_list[$p];   
  }else{      return "该属性不存在!";    }  }  
  function __unset($prop){    unset($this->prop_list[$prop]);  }}
  $a1 = new A();$a1->p1 = 1;//不存在的属性名赋值,此时会调用_set(),并传过去"p1"和1
  echo "<br />a1->p1:" . $a1->p1;//不存在的属性名取值,此时会调用_get(),并传过去"p1"
  //下面演示unset销毁一个不存在的属性
  unset($a1->p1);echo "<br />a1->p1:" . $a1->p1;

运行结果为:

a1->p1:1
a1->p1:该属性不存在!

下面的例子中,声明一个Person类,并将所有的成员属性设置成private的。在类中添加自定义的“__isset()”和“__unset()”两个方法。在类外部使用“isset()”和“unset()”函数时,会自动调用这两个方法。代码如下:

class Person{  private $name; //此属性被封住 
private $sex;  private $age;  
function __construct($name='', $sex='男', $age){    
$this->name = $name;    
$this->sex = $sex;    
$this->age = $age;  }  
private function __isset($propertyName){  
//需要一个参数,是测定的私有属性的名称    
if($propertyName == 'name'){      
return false;  //返回假,不允许在类外部测定name属性    }    
return isset($this->$propertyName);  
//这里propertyName要加$符,因为这是参数,不是属性  }  
private function __unset($propertyName){    
if($propertyName == 'name')      
return; //退出方法,不允许删除对象中的name属性    
unset($this->$propertyName); //这里propertyName要加$符  }  
public function say(){    
echo "名字:" . $this->name . ",性别:" . $this->sex . ",年龄:" . $this->age . "<br />";  }}
$person = new Person("yeoman", "男", 23);var_dump(isset($person->name));  
//输出bool(false),不允许测定name属性
var_dump(isset($person->sex)); 
//输出bool(true),存在sex私有属性
var_dump(isset($person->age)); //输出bool(true),存在age私有属性
var_dump(isset($person->id)); //输出bool(false),测定对象中不存在id属性
unset($person->name); //删除私有属性name,但在 __unset()中不允许删除unset($person->sex); 
 //删除对象中的私有属性sex,删除成功
 unset($person->age);$person->say();  
 //对象中的sex和age属性被删除,输出:名字:yeoman,性别:,年龄:

运行结果:

boolean false
boolean true
boolean true
boolean false
名字:yeoman,性别:,年龄:

方法重载

当对一个对象不存在的实例方法进行“调用”时,会自动调用类中的__call()这个魔术方法;

当对一个类不存在的静态方法进行“调用”时,会自动调用类中的__callstatic()这个魔术方法。

例子:直接调用不存在的方法

ini_set('display_errors',1);class A{}$a = new A();$a->f1(); //不存在的方法

会报错,报错内容为:

Fatal error: Uncaught Error: Call to undefined method A::f1()

对上面报错作“优雅处理”:

class A{  //当对这个类的对象不存在的实力方法进行调用时,会自动调用本方法  //这个方法必须带2个形参:  
//$methodName:表示要调用的不存在的方法名;  
//$argument:表示要调用该不存在的方法时,所使用的实参数据,是一个数组。  
function __call($methodName, $argument){    
//echo "__call被调用了!";    
echo $methodName . "()方法不存在!";  }}
$a = new A();$a->f1(); //不存在的方法,但经过处理

运行结果为:

f1()方法不存在!

当对一个类不存在的静态方法进行“调用”时,会自动调用类中的__callstatic()这个魔术方法。和上面的处理类似。

希望本文所述对大家PHP程序设计有所帮助。

[!--infotagslink--]

相关文章

  • mysql_connect与mysql_pconnect的区别详解

    在mysql中我们会看到有两种常用的数据库连接模式,一种是长久连接,另一各是页面访问完之后就断了连接,下面我来分别介绍mysql_connect与mysql_pconnect的区别,有需要了解...2016-11-25
  • phpems SQL注入(cookies)分析研究

    PHPEMS(PHP Exam Management System)在线模拟考试系统基于PHP+Mysql开发,主要用于搭建模拟考试平台,支持多种题型和展现方式,是国内首款支持题冒题和自动评分与教师评分相...2016-11-25
  • PHP添加MongoDB扩展实例教程

    由于要使用mikoomi mongodb plugin插件,所以需要php对mongodb的扩展支持,默认通过源安装的php并没有mongodb的扩展支持,具体可以通过php -m|grep mongo 验证 。这里就结...2016-11-25
  • php身份证校验码的计算例子

    下面来给各位同学介绍一个php身份证校验码的计算例子,希望本函数代码能帮助到各位同学哦。 例子 代码如下 复制代码 public function id_ver...2016-11-25
  • PHP session_start()很慢问题分析与解决办法

    本文章来给各位同学介绍一下关于PHP session_start()很慢问题分析与解决办法,希望碰到此问题的同学可进入参考。 最近在做东西的时候发现一个问题 有一个接口挂...2016-11-25
  • php读取zip文件(删除文件,提取文件,增加文件)实例

    下面小编来给大家演示几个php操作zip文件的实例,我们可以读取zip包中指定文件与删除zip包中指定文件,下面来给大这介绍一下。 从zip压缩文件中提取文件 代...2016-11-25
  • php生成二维码中文乱码问题解决方法

    最近做了个扫描二维码得到vcard的项目,遇到一个问题,有一部分生成完的二维码,用android系统手机扫描后得到的vcard中的中文姓名是乱码,经过比对发现,这部分vcard中ORG这个...2016-11-25
  • php中网页添加到桌面快捷方式方法

    我们经常会在网站中看到可以直接把网站以快捷方式保存到自己的电脑中,然后只要点击就可以实现进入网了,那么php中怎么把网页添加到桌面快捷方式呢。 功能简单,直接上...2016-11-25
  • php5.3下使用php管理crontab计划任务

    php5.3或以上版本可以使用php管理crontab计划任务,下面我先来体验一下,有需要学习了解的朋友可进入参考。 1.使用php-crontab-manager管理计划任务 要求 PHP>=5.3...2016-11-25
  • ASP/PHP sql注入语句整理大全

    SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作 标准注入语句1.判...2016-11-25
  • php svn操作类

    以前我们开发大型项目时都会用到svn来同步,因为开发产品的人过多,所以我们会利用软件来管理,今天发有一居然可以利用php来管理svn哦,好了看看吧。 代码如下 ...2016-11-25
  • php中json_decode()和json_encode()用法与中文不显示解决办法

    本文章介绍了关于php中json_decode()和json_encode()用法与中文不显示解决办法,有需要的朋友可以参考一下下。 php中json_decode()和json_encode() 1.json_decode(...2016-11-25
  • php正确禁用eval函数与误区介绍

    eval函数在php中是一个函数并不是系统组件函数,我们在php.ini中的disable_functions是无法禁止它的,因这他不是一个php_function哦。 eval()针对php安全来说具有很...2016-11-25
  • php中eval()函数操作数组的方法

    在php中eval是一个函数并且不能直接禁用了,但eval函数又相当的危险了经常会出现一些问题了,今天我们就一起来看看eval函数对数组的操作 例子, <?php $data="array...2016-11-25
  • PHP 数据库缓存Memcache操作类

    操作类就是把一些常用的一系列的数据库或相关操作写在一个类中,这样调用时我们只要调用类文件,如果要执行相关操作就直接调用类文件中的方法函数就可以实现了,下面整理了...2016-11-25
  • phpexcel导出数据身份证后四位0000解决办法

    在php中我们如果要导入excel数据我们通常会使用phpexcel插件了,但是有朋友会发与使用phpexcel导出数据出现身份证后四位是0000情况了,下面我们就来看解决办法。 最...2016-11-25
  • PHP7快速编译安装的步骤

    编译安装非常的简单了我们现在的php版本已经到了php7了,下文小编来为各位介绍一篇关于PHP7快速编译安装的步骤,希望文章能够帮助到各位。 一、安装必要一些依赖 yum...2016-11-25
  • php KindEditor文章内分页的实例方法

    我们这里介绍php与KindEditor编辑器使用时如何利用KindEditor编辑器的分页功能实现文章内容分页,KindEditor编辑器在我们点击分页时会插入代码,我们只要以它为分切符,就...2016-11-25
  • PHP成员变量获取对比(类成员变量)

    下面本文章来给大家介绍在php中成员变量的一些对比了,文章举了四个例子在这例子中分别对不同成员变量进行测试与获取操作,下面一起来看看。 有如下4个代码示例,你认...2016-11-25
  • php 中file_get_contents超时问题的解决方法

    file_get_contents超时我知道最多的原因就是你机器访问远程机器过慢,导致php脚本超时了,但也有其它很多原因,下面我来总结file_get_contents超时问题的解决方法总结。...2016-11-25