
静态方式调用非静态方法.doc
6页静态方式调用非静态方法静态方式调用非静态方法php 是个很诡异的语言当然,这是对学习过 C++或者 Java 等面向对象语言的人来说php 可以定义静态的方法,然后通过 className::staticMethod()形式来调用非静态的方法,当然通过 classObject->nonStaticMethod()使用这个其他语言中也是如此,没什么大惊小怪的可是,您能用 className::nonStaticMethod()调用非静态方法吗?这方面恐怕 Java 和 C++要冷汗直流了其实,php 自己也是满脸黑线为什么这么说呢?先来看看面向对象的静态和非静态面向对象的语言中,都会支持静态方法静态方法,属于类的固定资产的;非静态的方法,属于类的实例的私有财产在内存中,静态方法,对于整个类也就只存了这么一份;无论你 new 了多少个实例对象,它们共用的也就这么一份对于非静态的就不一样了,你 new 几个,内存就给你 new 几份另外,静态方法内不可以调用非静态方法,非静态方法内却可以调用静态方法这个就是静态和非静态的区别面向对象用 static 关键字来定义静态未被标明是静态的方法,是不可以用类名加两个冒号的形式调用的。
php 和其它很有区别的一点就是这个了:php 中未被标明是静态的方法,也可以用类名加两个冒号的形式调用那么为什么 php 有这种语法?又为什么感到很无奈呢?-----以下说明 php 无奈的故事据相关资料改编,已经过演义处理--------php 之所以发展如此迅速,得益于它的速度作为脚本语言,php 追求高速度和简洁方便,所以选择了解释执行和使用过程方法后来为了与国际接轨,引入了面向对象的概念而就是在引入这个面向对象的特征时,发生了一件令 php 目瞪口呆,最终无可奈何的事情面向对象有个很重要的概念就是继承在继承中,子类如果覆盖父类的方法,同时需要调用父类的同名方法,该怎么办呢?php4 版本提供了这样一种方法:parentClassName::method()提出此种方法之时,有识之士已经发现了问题:这个调用方式,不正是静态方法的调用方式吗?php4 随即答曰:不碍事类中使用时,可以判断此方式为子类正在调用父类方法;非类中使用时,就判断为静态调用了所需要的只是发现此种调用时查询一下方法映射就好了其实,一想,也确实是那么回事php4 后来想想,如果每次调用都检验一下此次调用是否合法,那多少也会影响性能,不如这个问题就交给程序员去控制吧:他们会知道只在类中使用此形式的调用的。
唉,可惜天不遂人愿php4 低估了程序员们的创造力!程序员们很快发现了这个方式,并且不余遗力地使用起来许多集成的 API 也开始使用这种怪癖的方式php 无奈了,随即在 php5 中引入了另一种方式,使用关键字 parent 来调 用父类函数:parent::method()但是,想要放弃 php 的非静态方法的静态调用,着实是不再可能了不过,话说回来,这种 php 的怪癖方式,有什么好处吗?性能和内存占用方面如何呢?于是我开始推理了:定义了一个非静态的方法,静态调用时,php首先转换此方法为静态定义,加载入静态内存区域,然后执行通常一次业务,只使用一个业务处理类中的一个方法,如果使用非静态定义,静态调用,内存中岂不是只加载了这个业务类中的一个方法,不是就实现了静态方法的按需加载吗?岂不是要省下一部分内存?性能方面,无论是静态调用,还是对象调用,反正都是执行一个方法,性能还不是一样?并且静态调用非静态定义方法还省了一个 new 语句这么想的同时,手就开始写上了那么实际如何呢?我做了一个小测试PHP codet::start();t::end(); //消除 t 类首次加载的影响t::start();model_profile_base::getBaseInfo($uid);t::end();t::start();$model = new model_profile_base();$model->getBaseInfo($uid);t::end();model_profile_base 是处理基本资料的一个业务类,比较复杂,比较接近于项目中的业务处理实际。
下面是用到的计时和统计内存的 t 类的定义:PHP codeStart @'.self::$start_time.'('.self::$start_memory.')|-----';}public static function end(){self::$end_time = microtime_float();self::$end_memory = memory_get_usage();echo 'End @'.self::$end_time.'('.self::$end_memory.') :';echo '|======= 共耗时:'.(self::$end_time-self::$start_time).',共用内存:'.(self::$end_memory-self::$start_memory);}}第二行是静态调用非静态方法,第三行是正常调用非静态方法然后,我发现我的推理悲剧了刷了好几次页面,统计结果在数量级上都差不多静态调用非静态方法无论内存占用还是性能上都不敢恭维这样的结果有点令人咂舌那么,再试一下循环执行多次的结果:PHP codet::start();t::end(); //消除 t 类首次加载的影响t::start();for($i=0; $igetBaseInfo($uid);t::end();于是更让人无语的结果出来了:PHP codeStart @1287562243.5799(1009372)|-----End @1287562243.5799(1009372) :|======= 共耗时:3.0040740966797E-5,共用内存:0Start @1287562243.58(1009372)|-----End @1287562244.1532(1587544) :|======= 共耗时:0.57321000099182,共用内存:578172Start @1287562244.1532(1587544)|-----End @1287562244.6921(1587744) :|======= 共耗时:0.53887605667114,共用内存:200 除了两种方式时间上开始接近外(并且还是正常调用比较利索) ,内存上仍然有天壤之别。
失望之余,查了下网上,发现也有人做了类似的测试我就直接把结果拷上来吧:(可能光看结果,会感觉有点难于理解,可以在这里找到详细说明:http://vega.rd.no/articles/php-static-method-performance)测试结果 (ORDER BY time DESC):PHP code============Which method========================Time======Inline calculation 0.0805 sNormal function call 0.3438 sNormal method called through object 0.4118 sStatic method called statically 0.4280 sUnspecified method called through object() 0.4294 sUnspecified method called statically() 0.6960 s如此看来,静态调用非静态方法在性能和内存上都不占优势;另外,此种调用方法容易产生维护混乱。
那么,来个短而有力的总结:静态调用非静态方法不可取。












