总结:

(1)__get($property_name):获取私有属性$name值时,此对象会自动调用该方法,将属性name值传给参数$property_name,通过这个方法的内部

执行,返回我们传入 的私有属性的值。

(2)__set($property_name, $value):直接给私有属性赋值时,此对象会自动调用该方法,把属性比如name传给$property_name, 把要赋的值

“zhangsan”传给$value,通过这个方法的执行,达到赋值的目的。

(3)__tostring()                : 当直接输出句柄(可以理解为一个实例)时,会自动执行__tostring()方法。

1.__set()与__get().

一般来说,总是把类的属性定义为private,这更符合现实的逻辑。但是,对属性的读取和赋值操作是非常频繁的,因此在 PHP5中,预定义了两个函数

“__get()”和“__set()”来获取和赋值其属性,以及检查属性的“__isset()”和删除属性的方法 “__unset()”。

我们为每个属性做了设置和获取的方法,在PHP5中给我们提供了专门为属性设置值和获 取值的方法,“__set()”和“__get()”这两个方法,这两个方法不是默认存在的,

而是我们手工添加到类里面去的,像构造方法 (__construct())一样, 类里面添加了才会存在,可以按下面的方式来添加这两个方法,当然也可以按个人的风格来添加:

//__get()方法用来获取私有属性
public function __get($property_name)
{if(isset($this->$property_name)){return($this->$property_name);}else{return(NULL);}
}//__set()方法用来设置私有属性
public function __set($property_name, $value){
$this->$property_name = $value;
}

__get()方法:这个方法用来获取私有成员属性值的,有一个参数,参数传入 你要获取的成员属性的名称,返回获取的属性值,这个方法不用我们手工的去调用,因为我们也可以把这个方法做成私有的方法,是在直接获取私有属性的时候对象 自动调用的。因为私有属性已经被封装上了,是不能直接获取值的(比如:“echo $p1->name”这样直接获取是错误的),但是如果你在类里面加上了这个方法,在使用“echo $p1->name”这样的语句直接获取值的时候就会自动调用__get($property_name)方法,将属性name传给参 数$property_name,通过这个方法的内部执行,返回我们传入的私有属性的值。如果成员属性不封装成私有的,对象本身就不会去自动调用这个方 法。

__set()方法:这个方法用来为私有成员属性设置值的,有两个参数,第一个参数为你要为设置值的属性名,第二个参数是要给属性设置的值, 没有返回值。这个方法同样不用我们手工去调用,它也可以做成私有的,是在直接设置私有属性值的时候自动调用的,同样属性私有的已经被封装上

了, 如果没有__set()这个方法,是不允许的,比如:$this->name=‘zhangsan’, 这样会出错,但是如果你在类里面加上了__set($property_name, $value)这个方法,在直接给私有属性赋值的时候,就会自动调用它,把属性比如name传给$property_name, 把要赋的值“zhangsan”传给$value,通过这个方法的执行,达到赋值的目的。如果成员属性不封装成私有的,对象本身就不会去自动调用这个方 法。为了不传入非法的值,还可以在这个方法给做一下判断。代码如下:

<?php
class Person {//下面是人的成员属性, 都是封装的私有成员private $name; //人的名子private $sex; //人的性别private $age; //人的年龄//__get()方法用来获取私有属性public function __get($property_name) {echo "在直接获取私有属性值的时候,自动调用了这个__get()方法<br>";if (isset ( $this->$property_name )) {return ($this->$property_name);} else {return (NULL);}}//__set()方法用来设置私有属性public function __set($property_name, $value) {echo "在直接设置私有属性值的时候,自动调用了这个__set()方法为私有属性赋值<br>";$this->$property_name = $value;}
}

$per=new person();$per->name="shirayner";  //此时$per自动调用__set($property_name, $value)方法echo $per->name;        //此时$per自动调用__get($property_name)方法

?>

2.__tostring() 

    TOstring(在这里故意这么写,是要说明PHP中方法不区分大小写,但实际开发中还需要注意规范)。当进行测试时,需要知道是否得出正确的数据。比如打印一个对象时,看看这个对象都有哪些属性,其值是什么,如果类定义了toString方法,就能在测试时,echo打印对象体,对象就会自动调用它所属类定义的toString方法,格式化输出这个对象所包含的数据。如果没有这个方法,那么echo一个对象将报错,例如“Catchable fatal error:Object of class Account could not be converted tostring”语法错误,实际上这是一个类型匹配失败错误。不过仍然可以用print_r()和var_dump()函数输出一个对象。当然,toString是可以定制的,所提供的信息和样式更丰富。
<?php
class Account{
public $user=1;
private $pwd=2;
// 自定义的格式化输出方法
public function toString(){
return "当前对象的用户名是{$this->user},密码是{$this->pwd}";
}
}
$a=new Account();
echo $a;
echo PHP_EOL;
print_r($a);

运行这段代码发现,使用toString方法后,输出的结果是可定制的,更易于理解。实际上,PHP的toString魔术方法的设计原型来源于 Java。Java中也有这么一个方法,而且在Java中,这个方法被大量使用,对于调试程序比较方便。实际上,toString方法也是一种序列化,我 们知道PHP自带serialize/unserialize也是进行序列化的,但是这组函数序列化时会产生一些无用信息,如属性字符串长度,造成存储空 间的无谓浪费。因此,可以实现自己的序列化和反序列化方法,或者json_encode/json_decode也是一个不错的选择。

为什么直接echo一个对象就会报语法错误,而如果这个对象实现toString方法后就可以直接输出呢?原因很简单,echo本来可以打印一个对 象,而且也实现了这个接口,但是PHP对其做了个限制,只有实现toString后才允许使用。从下面的PHP源代码里可以得到验证:

ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMP|VAR|CV, ANY)
{
zend_op *opline = EX(opline);
zend_free_op free_op1;
zval z_copy;
zval *z = GET_OP1_ZVAL_PTR(BP_VAR_R);
// 此处的代码预留了把对象转换为字符串的接口
if (OP1_TYPE != IS_CONST &&
Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
zend_std_cast_object_tostring(z, &z_copy, IS_STRING TSRMLS_CC) == SUCCESS) {
zend_print_variable(&z_copy);
zval_dtor(&z_copy);
} else {
zend_print_variable(z);
}
 
FREE_OP1();
ZEND_VM_NEXT_OPCODE();
}

PHP中 对象自动调用的方法:__set()、__get()、__tostring()相关推荐

  1. php的set 方法调用,PHP中 对象自动调用的方法:set()、get()、tostring()

    总结: (1)__get($property_name):获取私有属性$name值时,此对象会自动调用该方法,将属性name值传给参数$property_name,通过这个方法的内部 执行,返回我们传 ...

  2. 在C#中,当您在null对象上调用扩展方法时会发生什么?

    本文翻译自:In C#, what happens when you call an extension method on a null object? Does the method get ca ...

  3. java对象数组_Java中对象数组的使用方法详解

    本文实例讲述了Java中对象数组的使用方法.分享给大家供大家参考,具体如下: 一 点睛 对象可以用数组来存放,通过下面两个步骤来实现. 1 声明以类为数据类型的数组变量,并用new分配内存空间给数组. ...

  4. java中的对象数组_Java中对象数组的使用方法详解

    本文实例讲述了java中对象数组的使用方法.分享给大家供大家参考,具体如下: 一 点睛 对象可以用数组来存放,通过下面两个步骤来实现. 1 声明以类为数据类型的数组变量,并用new分配内存空间给数组. ...

  5. 实列化对象 自动调用构造方法

    package day18;public class WaDIu {public static void main(String[] args) {//实列化对象 自动调用构造方法Student s ...

  6. 初始化方法-创建对象时自动调用初始化方法

    class Cat:def __init__(self):print("这是一个初始化方法")# self.属性名 = 属性的初始值self.name = "Tom&qu ...

  7. SVN在另类环境中实现自动提交的方法

    环境: SVN SERVER  172.16.1.100            (CentOS 5.5 X64) WEB SERVER  172.16.1.111            (CentOS ...

  8. 在vue中methods互相调用的方法

    在vue中methods互相调用的方法 转载于:https://www.cnblogs.com/macT/p/10212878.html

  9. 标签中的onclick调用js方法传递多个参数的解决方案

    标签中的onclick调用js方法传递多个参数的解决方案 参考文章: (1)标签中的onclick调用js方法传递多个参数的解决方案 (2)https://www.cnblogs.com/twohea ...

最新文章

  1. android——ImageLoader添加缓存
  2. 士兵杀敌(二)(线段树+树状数组)
  3. cache 的设计与实现--转载
  4. 中国汽车融资租赁业运营前景与投资战略规划报告2022-2028年版
  5. VTK:网格之CapClip
  6. promo和promotion
  7. SpingMVC ModelAndView, Model,Control以及参数传递
  8. Java-接口的定义与实现
  9. OpenSSL 宣布将开源许可证更改为 Apache 2.0
  10. SSLOJ 1298.网站计划
  11. 深入理解Java虚拟机运行时数据区
  12. 修改了下exeScope的导出函数功能,让它只导出函数名。。。
  13. Matlab 检测直线并求解直线方程
  14. matlab删掉txt文件中的数据,matlab中读取txt数据文件(txt文本文档)
  15. 二级路由添加网络打印机的方法
  16. 头条App项目测试实战(三)文章写评论功能用例设计
  17. python爬取图片代码可替换网站_Python爬虫(批量爬取某网站图片)
  18. 我的世界服务器显示空岛等级,mc空岛每种方块等级 | 手游网游页游攻略大全
  19. 大学计算机基础教程第1章计算机概述总结
  20. 基于Docker的Redis集群搭建

热门文章

  1. ***关于WP的邮件无法发送问题的总结(原创)
  2. 在Leangoo里怎么设置看板周期?
  3. mykernel编译过程中问题解决
  4. 【转】你没有变强是因为你一直很舒服
  5. SQL注入漏洞全接触--高级篇
  6. Linux下添加普通帐号
  7. 各种排序算法及其实现总结
  8. SiteMapCreator 发布 (Open Source)
  9. 华为首款鸿蒙设备正式入网,华为首款鸿蒙设备正式入网:麒麟9000+挖孔全面屏,价格感人!...
  10. rfc mail content-type