首页 > php教程 > php手册 > 正文

1.2魔术方法和延迟静态绑定

php中文网
发布: 2016-08-23 09:03:38
原创
1182人浏览过

一.魔术方法:

  1.__get,__set

  __get:获取一个不可访问的属性时触发(不可访问指属性不存在,或者没有访问权限)

  __set:为一个不可访问的属性赋值的时候触发

  2.__isset,__unset

  __isset:当用isset()函数判断一个不可访问的属性时触发

  __unset:当用unset()函数操作一个不可访问的属性时触发

  3.__call,__callStatic

  __call:当调用一个不可访问的方法时触发

  __callStatic:当调用一个不可访问的静态方法时触发

  4.__construct,__destruct

  __construct:初始化一个对象时触发

  __destruct:对象销毁,或者脚本执行完时触发

  5.__autoload

  __autoload:当使用一个不可访问的类时触发

  6.__clone

  __clone:对象被克隆时触发

  7.__sleep,__wakeup

  __sleep:使用serialize时触发

  __wakeup:使用unserialize时触发

  8.__toString,__invoke

  __toString:当一个对象被当做字符串来操作时触发,如$obj是一个对象,echo $obj,就会触发__toString

  __invoke:当一个对象被当做函数来使用时触发,如$obj是一个对象,$obj()就会触发__invoke

 

二.延迟静态绑定

  抛开概念看例子理解就好:

  首先延迟静态绑定是怎么出现的?看下面例子:

class A{<br />}<br />class B extends A{<br />    public static function out(){<br />        return new self();<br />    }<br />}<br />class C extends A{<br />    public static function out(){<br />        return new self();<br />    }<br />}<br />var_dump(B::out());//结果是object(B)#1 (0) { }<br />var_dump(C::out());//结果是object(C)#1 (0) { }<br />然后我们将子类中相同的代码抽取到父类class A中,变成:
登录后复制
class A{<br />    public static function out(){<br />        return new self();<br />    }<br />}<br />class B extends A{<br />}<br />class C extends A{<br />}<br />var_dump(B::out());//结果是object(A)#1 (0) { }<br />var_dump(C::out());//结果是object(A)#1 (0) { }<br />这个结果显然不是我们想要的,这里的问题主要是因为self指代的是它所在的类.这里self在类A里面,所以返回的永远是类A的对象,<br />而我们想要的是让out()方法返回调用它的类的对象而不是它所在的类的对象.怎么办?<br />此时我们马上可以想到$this可以代表调用它的对象,但是out()是一个静态方法,里面是不能出现$this的,怎么办?<br />用static.它也代表调用它的对象如:
登录后复制
class A{<br />    public static function out(){<br />        return new static();<br />    }<br />}<br />class B extends A{<br />}<br />class C extends A{<br />}<br />var_dump(B::out());//结果是object(B)#1 (0) { }<br />var_dump(C::out());//结果是object(C)#1 (0) { }<br />这样就好了.这就是延迟静态绑定.<br /><br />在看下面的例子:
登录后复制

为什么是这个结果呢?我们分析一下:

首先对象c调用get()方法,但是在类C中没有找到,于是它去类B中找,找到了.然后执行这个get方法,

先执行A::foo(); 类A会直接调用它自己的foo(),输出`fooA`,然后调用out,很明显这里调用static::out()的就是类A,所以输出的类名也是A.(这里侧重于类A)

再执行parent::foo(); parent表示父类,这里会去执行类A中的foo(),输出`fooA`,然后执行static::out(),此时调用这个static的不是类A,而是类C,因为parent代表的是父类,但不代表具体哪一个类(这里侧重于父类中的方法,而不管父类是谁).

然后执行self::foo(); self表示它所在的类(类B),它先执行foo(),没有再去父类中找,所以输出`fooA`,然后执行static::out(),同理这里使用static的不是类A,而是类C,self虽然代表类B,但是self不能代表一个具体的类.

简单点说:对象c开始执行get()-->A::foo();此时链子就断了,变成由类A直接去调用foo()了,和对象c没关系了.这里的static当然指的是类A.

     接着,对象c-->parent::foo()-->类A中的foo()-->static::out(),这里的parent说白了就是一个指向作用,即执行谁的foo()方法.所以可以理解为对象c调用类A中的foo方法.那么foo中的static代表类C

     最后,对象c-->self::foo()-->类A中的foo()-->static::out(),同上,这里的self也是一个指向的作用,但是最终还是到了类A.可以理解为对象c调用类A中的foo方法.那么foo中的static代表类C

 

登录后复制
<br /><br />
登录后复制
最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号