PHP静态调用非静态方法的应用分析


Posted in PHP onMay 02, 2013

静态调用非静态方法!!这在java,c#中是不可想象的,也是绝对不行的。这样的错误在这些语言中会在编译阶段就被指出错误的。但是对于php这样的动态语言呢?首先这个是语法没有错误的,php ?l 找不出错误来的。如果运行呢?
先看一个例子

<?php 
class myClass 
{ 
    private $name = "myClass";     public function echoName(){ 
        echo $this->name; 
    } 
    public function getName(){ 
        $this->echoName(); 
    } 
} 
class newClass 
{ 
    private $name = "newClass"; 
    public function echoName(){ 
        echo $this->name; 
    } 
    public function test() { 
        myClass::getName(); 
        echo "\n"; 
    } 
} 
$app = new newClass(); 
$app->test();

这个代码的最终调用结果是什么呢?(运行环境PHP 5.3.10 )

PHP静态调用非静态方法的应用分析

看这个结果,有几个地方值得注意:

首先是myClass::getName() 这是一个静态函数的调用
但是看一下myClass的getName()函数,它却并不是一个静态函数。

其次返回的结构
先是返回PHP Strict Standards Error。熟悉php的人应该知道,Strict Error是php的编码标准化警告,一般是由于php为了保持向前兼容而报出的错误。那这么说,非静态函数的静态调用在php5.3之前的某个版本是允许的,只是在后面的版本是不被建议使用!!

好了,如果你现在将Strict Error在error_reporting中注释掉,返回结果就变成了newClass!!

在php4版本的时候,子类需要调用父类的方法,但是子类又有一个同名的方法,因此不能使用$this,于是php4提供了(parentClassName::method())这样的方法。(当然php5增加了parent这个关键字)

但是php4提供的这个方法实际上就是允许了静态调用一个非静态方法!!后台由于需要向前兼容的原因,这个特性也就变成了不能删除的特性了(必须保证前面版本的代码能在后一版本的php环境中运行)。

只是增加了Strict Error来对这种调用进行提示。

底层实现原因
好了,对于为什么会出现这个情况的实现原因, 鸟哥的这篇文章有说明 http://www.laruence.com/2012/06/14/2628.html

首先需要颠覆自己的观点,什么是静态调用?并不是说有::就是静态调用,而是看calling scope。

“ $this指针指向的对象就是这个方法被调用时刻的calling scope.”

 

我换一种句子翻译:

静态调用是没有calling scope的,非静态调用$this->abc() 中的$this指向的对象就是calling scope。

Calling scope是当每一句调用的时候被传递的。

理解下面的代码:

<?php 
 class A { 
    public function __construct() { 
    } 
 } 
  class B extends A { 
    public function __construct() { 
        parent::__construct(); 
   } 
}

这里的parent::_construct()是子类将calling scope转化为父类A的calling scope。这个并不是静态调用。

回到最上面的例子
myClass::getName();

这个时候由于没有使用parent这样的关键字,也没有对$this重新赋值,因此calling scope并没有改变,仍然是$app。就是说这个时候,所有出现的$this指针都是指向$app的。

好了,下面的事情就很好理解了, echo $this->name; 自然就是调用calling scope的name属性了。

PHP 相关文章推荐
php中截取字符串支持utf-8
Jan 18 PHP
PHP与MySQL开发的8个技巧小结
Dec 17 PHP
php mssql扩展SQL查询中文字段名解决方法
Oct 15 PHP
Php中使用Select 查询语句的实例
Feb 19 PHP
php查询whois信息的方法
Jun 08 PHP
PHP程序中使用adodb连接不同数据库的代码实例
Dec 19 PHP
PHP类和对象相关系统函数与运算符小结
Sep 28 PHP
php事件驱动化设计详解
Nov 10 PHP
PHP实现文件上传功能实例代码
May 18 PHP
thinkphp ajaxfileupload实现异步上传图片的示例
Aug 28 PHP
thinkPHP框架实现多表查询的方法
Jun 14 PHP
php面试实现反射注入的详细方法
Sep 30 PHP
Mysql中分页查询的两个解决方法比较
May 02 #PHP
记录mysql性能查询过程的使用方法
May 02 #PHP
基于MySQL分区性能的详细介绍
May 02 #PHP
php中使用$_REQUEST需要注意的一个问题
May 02 #PHP
PHP执行批量mysql语句的解决方法
May 02 #PHP
PHP闭包(Closure)使用详解
May 02 #PHP
PHP5中Cookie与 Session使用详解
Apr 30 #PHP
You might like
Discuz! 5.0.0论坛程序中加入一段js代码,让会员点击下载附件前自动弹出提示窗口
2007/04/18 PHP
DEDE实现转跳属性文档在模板上调用出转跳地址
2016/11/04 PHP
PHP实现更改hosts文件的方法示例
2017/08/08 PHP
thinkphp框架表单数组实现图片批量上传功能示例
2020/04/04 PHP
JS 图片缩放效果代码
2010/06/09 Javascript
jQuery 遍历-nextUntil()方法以及prevUntil()方法的使用介绍
2013/04/26 Javascript
判断是否安装flash player及当前版本的JS代码
2013/08/08 Javascript
JavaScript实现信用卡校验方法
2015/04/07 Javascript
详解VUE2.X过滤器的使用方法
2018/01/11 Javascript
angularjs手动识别字符串中的换行符方法
2018/10/02 Javascript
VUE基于NUXT的SSR 服务端渲染
2018/11/30 Javascript
Vue实现商品分类菜单数量提示功能
2019/07/26 Javascript
Python3实现从文件中读取指定行的方法
2015/05/22 Python
python清除指定目录内所有文件中script的方法
2015/06/30 Python
利用Python破解斗地主残局详解
2017/06/30 Python
解决Mac安装scrapy失败的问题
2018/06/13 Python
python接口自动化测试之接口数据依赖的实现方法
2019/04/26 Python
Python插入Elasticsearch操作方法解析
2020/01/19 Python
python 递归调用返回None的问题及解决方法
2020/03/16 Python
Python 实现进度条的六种方式
2021/01/06 Python
局部内部类是否可以访问非final变量?
2013/04/20 面试题
职工趣味运动会方案
2014/02/10 职场文书
春节联欢晚会主持词范文
2014/03/24 职场文书
校园绿化美化方案
2014/06/08 职场文书
伦敦奥运会的口号
2014/06/21 职场文书
《周恩来的四个昼夜》观后思想汇报范文两篇
2014/09/10 职场文书
师德标兵先进事迹材料
2014/12/19 职场文书
给老师的感谢信
2015/01/20 职场文书
淮海战役观后感
2015/06/11 职场文书
2016幼儿园中班开学寄语
2015/12/03 职场文书
2016年第32个教师节红领巾广播稿
2015/12/18 职场文书
CSS中em的正确打开方式详解
2021/04/08 HTML / CSS
JavaScript的Set数据结构详解
2022/02/18 Javascript
浅析JavaScript中的变量提升
2022/06/01 Javascript
分享很少见很有用的SQL功能CORRESPONDING
2022/08/05 MySQL
JavaScript实现音乐播放器
2022/08/14 Javascript