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类
Jul 15 PHP
PHP提取中文首字母
Apr 09 PHP
php中计算中文字符串长度、截取中文字符串的函数代码
Aug 09 PHP
比较discuz和ecshop的截取字符串函数php版
Sep 03 PHP
深入php多态的实现详解
Jun 09 PHP
浅析SVN常见问题及解决方法
Jun 21 PHP
php数组中包含中文的排序方法
Jun 03 PHP
php计算年龄精准到年月日
Nov 17 PHP
Zend Framework教程之模型Model用法简单实例
Mar 04 PHP
php实现网页端验证码功能
Jul 11 PHP
PHP实现生成数据字典功能示例
May 24 PHP
php使用mysqli和pdo扩展,测试对比连接mysql数据库的效率完整示例
May 09 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
解析PHP提交后跳转
2013/06/23 PHP
浅析echo(),print(),print_r(),return之间的区别
2013/11/27 PHP
利用yahoo汇率接口实现实时汇率转换示例 汇率转换器
2014/01/14 PHP
php实现基于微信公众平台开发SDK(demo)扩展的方法
2014/12/22 PHP
PHP微信API接口类
2016/08/22 PHP
PHP大文件分块上传功能实例详解
2019/07/22 PHP
基于php解决json_encode中文UNICODE转码问题
2020/11/10 PHP
js 表格隔行颜色
2009/12/02 Javascript
jquery实现翻动fadeIn显示的方法
2015/03/05 Javascript
全面解析Bootstrap中transition、affix的使用方法
2016/05/30 Javascript
JS中正则表达式全局匹配模式 /g用法详解
2017/04/01 Javascript
vue子组件使用自定义事件向父组件传递数据
2017/05/27 Javascript
JS中type=&quot;button&quot;和type=&quot;submit&quot;的区别
2017/07/04 Javascript
seajs实现强制刷新本地缓存的方法分析
2017/10/16 Javascript
vue实现随机验证码功能的实例代码
2019/04/30 Javascript
vue中使用WX-JSSDK的两种方法(推荐)
2020/01/18 Javascript
javascript实现滚轮轮播图片
2020/12/13 Javascript
[01:10:27]DOTA2-DPC中国联赛正赛 SAG vs XG BO3 第二场 3月5日
2021/03/11 DOTA
Python抓取框架Scrapy爬虫入门:页面提取
2017/12/01 Python
Python装饰器原理与简单用法实例分析
2018/04/29 Python
使用Selenium破解新浪微博的四宫格验证码
2018/10/19 Python
对python中url参数编码与解码的实例详解
2019/07/25 Python
Python数据持久化存储实现方法分析
2019/12/21 Python
pytorch 实现将自己的图片数据处理成可以训练的图片类型
2020/01/08 Python
python next()和iter()函数原理解析
2020/02/07 Python
HTML5+CSS3实现机器猫
2016/10/17 HTML / CSS
详解快速开发基于 HTML5 网络拓扑图应用
2018/01/08 HTML / CSS
新秀丽拉杆箱美国官方网站:Samsonite美国
2016/07/25 全球购物
找到您丢失的钥匙、钱包和手机:Tile
2017/05/19 全球购物
科室工作的个人自我评价
2013/10/30 职场文书
小学安全教育材料
2014/02/17 职场文书
优秀教师单行材料
2014/12/16 职场文书
2015年银行工作总结范文
2015/04/01 职场文书
36个正则表达式(开发效率提高80%)
2021/11/17 Javascript
Python Django项目和应用的创建详解
2021/11/27 Python
提高系统的吞吐量解决数据库重复写入问题
2022/04/23 MySQL