作者: laruence()本文地址: http://www.laruence.com/2012/06/14/2628.html转载请注明出处 昨天在yaf交流群, 大草原同学批评我变懒了, blog很久没更新了, 今天刚好有人在segmentfalut上问了我一个问题, ?我在微博上也做了简单的解答, 不过感觉一句话说不清楚, 就写篇blog凑个数吧.
问题在这里, ?因为太长, 我就不copy过来了: 这是php中__call和__callstatic在被继承后会产生的bug?
这个问题乍看, 确实很容易让人迷惑, 但实际上, 造成这样的误解的根本原因在于: 在php中, 判断静态与否不是靠”::”(paamayim_nekudotayim)符号, 而是靠calling scope.
那么, 什么是calling scope?
在php中, 调用一个方法的时候, $this指针指向的对象就是这个方法被调用时刻的calling scope. 对于下面的例子:
在调用bar方法的时候, 处于一个没有calling scope域的上下文中, 所以这个是静态调用.
而对于如下的例子:
test();
在调用bar方法的时候, 处于一个$a对象的上下文中, 也就是说, 此时的calling scope是$a对象, 所以这个其实不是静态调用.
为了验证这一个结论, 请看下面的一个实际例子:
test();?>
输出什么呢?
object(a)#1 (0) {}
在调用bar的时候, 这个看似”静态”调用的调用, $this指针却是被赋值的, 指向的是$a对象, 那么这个还算静态调用么?
我举这个例子是为了说明这个问题, 但大家在实际的应用中, 大家尽量要避免使用”::”来调用一个非静态的方法, php也会对于这种调用给出一个strict 警告:
strict standards: non-static method foo::bar() should not be called statically, assuming $this from incompatible context
也许有人会说这个应该算bug吧? 其实不然, 更多的应该是错误使用造成的, 因为你在一个有calling scope的上下文中采用”静态的形式”调用了一个类的非静态方法所致.
那么php为什么要这么设计呢? 考虑下面的例子:
静态调用函数public function bar() 定义成 public static function bar() 再静态调用,$this指针不会被赋值。2012/06/20, wclssdn writes: 给力~~~ 不过. 看到那个$this竟然有值.. 还是a 我就诧异了.... 如果$this->bar2(); 那岂不是报bar2不存在a中? 看来写法的规范性是必须的啊~~ 我就一直没碰到过这问题.. 哈哈哈~~~2012/06/25, php爱好者 writes: 表示我是个规范的写代码的人,不过看了laruence的这篇文章,还是很有收获!2012/06/25, funlake writes: 给力,又学到东西了,感谢。2012/07/12, eason writes: 说实话,这种作用域的东西,在任何语言里都有。一般对javascript 运行机制,作用域,作用域链有深刻理解的人,再来看php的作用域那就更容易了。2012/08/09, 奇言妙事-文学奇谈小小说阅读xlinblog.sinaapp.com » blog archive » php的calling scope writes: [...] 本文地址: http://www.laruence.com/2012/06/14/2628.html [...]2012/08/12, php的calling scope树林/咖啡 成都专业php网站制作 | 树林/咖啡 成都专业php网站制作 writes: [...] 风雪之隅 ? php应用 posted in: php / tagged: php的calling, scope [...]2012/08/30, 疯狂的火星人 writes: 再看一遍!2012/09/13, php静态调用非静态方法 | 编程·早晨 writes: [...] 好了,对于为什么会出现这个情况的实现原因, 鸟哥的这篇文章有说明 http://www.laruence.com/2012/06/14/2628.html [...]2012/09/21, x6y6 writes: 用静态方法去调用一个非静态函数,这个为什么不干脆不报错呢,因为按照其他语言,比如java、c++是直接报错的。2012/09/21, x6y6 writes: 我有点奇怪,用调用静态方法的方法去调用一个非静态方法,为什么不干脆直接报错呢,因为按照其他语言,比如java、c++这种情况是直接报错的。2012/11/19, php静态调用非静态方法 « 成人免费资源三级分享网站 writes: [...] 好了,对于为什么会出现这个情况的实现原因, 鸟哥的这篇文章有说明 http://www.laruence.com/2012/06/14/2628.html [...]2012/11/28, jason writes: 学习了!!!2013/03/15, fxycarl writes: 怪不得我之前在用call_user_function调用对象的方法的时候会出现没在对象上下文的提示...2013/05/03, noname writes: 我觉得这是在php语言设计上有问题。related posts:如何获取一个变量的名字javascript作用域原理深入理解php原理之函数(introspecting php function)深入理解php原理之变量分离/引用(variables separation)深入浅出php(exploring php)copyright © 2010 风雪之隅 版权所有, 转载务必注明. 该feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发e-mail至my at laruence.com.(digital fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)
