第十五节--Zend引擎的发展_php教程-查字典教程网
第十五节--Zend引擎的发展
第十五节--Zend引擎的发展
发布时间:2016-12-29 来源:查字典编辑
摘要:/*+-------------------------------------------------------------------...

/*

+-------------------------------------------------------------------------------+

|=本文为Haohappy读<<CorePHPProgramming>>

|=中ClassesandObjects一章的笔记

|=翻译为主+个人心得

|=为避免可能发生的不必要的麻烦请勿转载,谢谢

|=欢迎批评指正,希望和所有PHP爱好者共同进步!

|=PHP5研究中心:http://blog.csdn.net/haohappy2004

+-------------------------------------------------------------------------------+

*/

第十五节--Zend引擎的发展

本章的最后一节,Zeev讨论了Zend引擎带来的对象模型,特别提到它与PHP的前几个版本中的模型有什么不同.

当1997年夏天,我们开发出PHP3,我们没有计划要使PHP具备面向对象的能力.当时没有任何与类和对象有关的想法.PHP3是一个纯粹面向过程的语言.但是,在1997.8.27的晚上PHP3alpha版中增加了对类的支持.增加一个新特性给PHP,当时仅需要极少的讨论,因为当时探索PHP的人太少.于是从1997年八月起,PHP迈出了走向面向对象编程语言的第一步.

确实,这只是第一步.因为在这个设计中只有极少的相关的想法,对于对象的支持不够强大.这个版本中使用对象仅是访问数组的一个很酷的方法而已.取代使用$foo[“bar”],你可以使用看起来更漂亮的$foo->bar.面向对象方法的主要的优势是通过成员函数或方法来储存功能.例子6.18中显示了一个典型的代码块.但是它和例6.19中的做法其实并没有太大不同.

Listing6.18PHP3object-orientedprogrammingPHP3中的面向对象编程

复制代码 代码如下:<?php

classExample

{

var$value="somevalue";

functionPrintValue()

{

print$this->value;

}

}

$obj=newExample();

$obj->PrintValue();

?>Listing6.19PHP3structuralprogrammingPHP3PHP3中的结构化编程

复制代码 代码如下:<?php

functionPrintValue($arr)

{

print$arr["value"];

}

functionCreateExample()

{

$arr["value"]="somevalue";

$arr["PrintValue"]="PrintValue";

return$arr;

}

$arr=CreateExample();

//UsePHP'sindirectreference

$arr["PrintValue"]($arr);

?>以上我们在类中写上两行代码,或者显示地传递数组给函数.但考虑到PHP3中这两种选择并没有任何不同,我们仍然可以仅把对象模型当成一种”语法上的粉饰”来访问数组.

想要用PHP来进行面向对象开发的人们,特别是想使用设计模式的人,很快就发现他们碰壁了.幸运地,当时(PHP3时代)没有太多人想用PHP来进行面向对象开发.

PHP4改变了这种情况.新的版本带来了引用(reference)的概念,它允许PHP的不同标识符指向内存中的同一个地址.这意味着你可以使用两个或更多的名称来给同一个变量命名,就像例6.20那样.

Listing6.20PHP4referencesPHP4中的引用

复制代码 代码如下:<?php

$a=5;

//$bpointstothesameplaceinmemoryas$a$b与$a指向内存中同个地址

$b=&$a;

//we'rechanging$b,since$aispointingto改变$b,指向的地址改变

//thesameplace-itchangestoo$a指向的地址也改变

$b=7;

//prints7输出7

print$a;

?>由于构建一个指向彼此的对象网络是所有面向对象设计模式的基础,这个改进具有非常重大的意义.当引用允许建立更多强大的面向对象应用程序,PHP对待对象和其它类型数据相同的做法带给开发者极大的痛苦.就像任何PHP4的程序员将会告诉你的,应用程序将会遭遇WTMA(WayTooManyAmpersands过多&)综合症.如果你想构建一个实际应用,你会感到极为痛苦,看看例6.21你就明白.

Listing6.21ProblemswithobjectsinPHP4PHP4中使用对象的问题

复制代码 代码如下:1classMyFoo{

2functionMyFoo()

3{

4$this->me=&$this;

5$this->value=5;

6}

7

8functionsetValue($val)

9{

10$this->value=$val;

11}

12

13functiongetValue()

14{

15return$this->value;

16}

17

18functiongetValueFromMe()

19{

20return$this->me->value;

21}

22}

23

24functionCreateObject($class_type)

25{

26switch($class_type){

27case"foo":

28$obj=newMyFoo();

29break;

30case"bar":

31$obj=newMyBar();

32break;

33}

34return$obj;

35}

36

37$global_obj=CreateObject("foo");

38$global_obj->setValue(7);

39

40print"Valueis".$global_obj->getValue()."n";

41print"Valueis".$global_obj->getValueFromMe()."n";

让我们一步步来讨论.首先,有一个MyFoo类.在构造函数里,我们给$this->me一个引用,并设定

我们有其它三个成员函数:一个设定this->value的值;一个返回this->value的值;另一个返回this->value->me的值.但是--$this不是相同的东西吗?MyFoo::getValue()和MyFoo::getValueFromMe()返回的值不是一样的吗?

首先,我们调用CreateObject("foo"),这会返回一个MyFoo类型的对象.然后我们调用MyFoo::setValue(7).最后,我们调用MyFoo::getValue()和MyFoo::getValueFromMe(),期望得到返回值7.

当然,如果我们在任何情况下都得到7,以上这个例子将不是本书中最没有意义的例子.所以我相信你已经猜到—我们得不到两个7这样的结果.

但是我们将得到什么结果,并且更重要地,为什么呢?

我们将得到的结果分别是7和5.至于为什么—--有三个很好的理由.

首先,看构造函数.当在构造函数内部,我们在this和this->me间建立引用.换句话说,this和this->me是同个东西.但是我们是在构造函数内.当构造函数结束,PHP要重新建立对象(newMyFoo的结果,第28行)分配给$obj.因为对象没有特殊化对待,就像其它任何数据类型一样,赋值X给Y意味着Y是X的一个副本.也就是说,obj将是newMyFoo的一个副本,而newMyFoo是一个存在于构造函数的对象.Obj->me怎么样呢?因为它是一个引用,它原封不动仍然指向原来的对象—this.Voila-obj和obj->me不再是同个东西了—改变其中一个另一个不变.

以上是第一条理由.还有其它类似于第一条的理由.奇迹般地我们打算克服实例化对象这个问题(第28行).一旦我们把CreateObject返回的值赋给global_object,我们仍然要撞上相同的问题—global_object将变成返回值的一个副本,并且再次地,global_object和global_object->me将不再相同.这就是第二条理由.

但是,事实上我们还走不了那么远—一旦CreateObject返回$obj,我们将破坏引用(第34行).这就是第三条理由.

那么,我们如何改正这些?有两个选择.一是在所有地方增加&符号,就像例6.22那样(第24,28,31,37行).二.如果你幸运地使用上了PHP5,你可以忘了以上这一切,PHP5会自动为你考虑这些.如果你想知道PHP5是如何考虑这些问题的,继续阅读下去.

Listing6.22WTMAsyndromeinPHP4PHP4中的WTMA综合症

复制代码 代码如下:1classMyFoo{

2functionMyFoo()

3{

4$this->me=&$this;

5$this->value=2;

6}

7

8functionsetValue($val)

9{

10$this->value=$val;

11}

12

13functiongetValue()

14{

15return$this->value;

16}

17

18functiongetValueFromMe()

19{

20return$this->me->value;

21}

22};

23

24function&CreateObject($class_type)

25{

26switch($class_type){

27case"foo":

28$obj=&newMyFoo();

29break;

30case"bar":

31$obj=&newMyBar();

32break;

33}

34return$obj;

35}

36

37$global_obj=&CreateObject("foo");

38$global_obj->setValue(7);

39

40print"Valueis".$global_obj->getValue()."n";

41print"Valueis".$global_obj->getValueFromMe()."n";

PHP5是第一个把对象看成与其它类型数据不同的PHP版本.从用户的角度看,这证明它非常明白的方式—在PHP5中,对象总是通过引用来传递,而其它类型数据(如integer,string,array)都是通过值来传递.最显著地,没有必要再用&符号来表示通过引用来传递对象了.

面向对象编程广泛利用了对象网络和对象间的复杂关系,这些都需要用到引用.在PHP的前些版本中,需要显示地指明引用.因此,现在默认用引用来移动对象,并且只有在明确要求复制时才复制对象,这样比以前更好.

它是如何实现的呢?

在PHP5之前,所有值都存在一个名为zval(ZendValue)的特殊结构里.这些值可以存入简单的值,如数字和字符串,或复杂的值如数组和对象.当值传给函数或从函数返回时,这些值会被复制,在内存的另一个地址建立一个带有相同内容的结构.

在PHP5中,值仍存为zval结构中,但对象除外.对象存在一个叫做ObjectStore的结构里,并且每个对象有一个不同的ID.Zval中,不储存对象本身,而是存着对象的指针.当复制一个持有对象的zval结构,例如我们把一个对象当成参数传给某个函数,我们不再复制任何数据.我们仅仅保持相同的对象指针并由另一个zval通知现在这个特定的对象指向的ObjectStore.因为对象本身位于ObjectStore,我们对它所作的任何改变将影响到所有持有该对象指针的zval结构.这种附加的间接作用使PHP对象看起来就像总是通过引用来传递,用透明和有效率的方式.

使用PHP5,我们现在可以回到示例6.21,除去所有的&符号,一切代码都仍然可以正常工作.当我们在构造函数(第4行)中持有一个引用时一个&符号都不用.

相关阅读
推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
  • 大家都在看
  • 小编推荐
  • 猜你喜欢
  • 最新php教程学习
    热门php教程学习
    编程开发子分类