日期:2011-05-19  浏览次数:20453 次

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

本章的最后一节,Zeev讨论了Zend引擎带来的对象模型,特别提到它与PHP的前几个版本中的模型有什么不同.
当1997年夏天,我们开发出PHP3, 我们没有计划要使PHP具备面向对象的能力. 当时没有任何与类和对象有关的想法. PHP3是一个纯粹面向过程的语言. 但是,在1997.8.27的晚上PHP3 alpha版中增加了对类的支持. 增加一个新特性给PHP,当时仅需要极少的讨论,因为当时探索PHP的人太少. 于是从1997年八月起, PHP迈出了走向面向对象编程语言的第一步.

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

Listing 6.18 PHP 3 object-oriented programming PHP3中的面向对象编程
<?PHP 

   class Example 

   { 

       var $value = "some value"; 

       function PrintValue() 

       { 

           print $this->value; 

       } 

   } 

   $obj = new Example(); 

   $obj->PrintValue(); 

?> 



Listing 6.19 PHP 3 structural programming PHP3 PHP3中的结构化编程
<?PHP 

   function PrintValue($arr) 

   { 

       print $arr["value"]; 

   } 



   function CreateExample() 

   { 

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

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



       return $arr; 

   } 



   $arr = CreateExample(); 



   //Use PHP's indirect reference 

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

?> 


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

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

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

Listing 6.20 PHP 4 references PHP4中的引用
<?PHP 

   $a = 5; 



   //$b points to the same place in memory as $a $b与$a指向内存中同个地址 

   $b = &$a; 



   //we're changing $b, since $a is pointing to 改变$b,指向的地址改变 

   //the same place - it changes too $a指向的地址也改变 

   $b = 7; 



   //prints 7  输出7 

   print $a; 

?> 



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

Listing 6.21 Problems with objects in PHP 4 PHP4中使用对象的问题
1    class MyFoo { 

2        function MyFoo() 

3        { 

4            $this->me = &$this; 

5            $this->value = 5; 

6        } 

7 

8        function setValue($val) 

9        { 

10            $this->value = $val; 

11        } 

12 

13        function getValue() 

14        { 

15            return $this->value; 

16        } 

17 

18        function getValueFromMe() 

19        { 

20            return $this->me->value; 

21        } 

22    } 

23 

24        function CreateObject($class_type) 

25        { 

26            switch ($class_type) { 

27                case "foo": 

28                    $obj = new MyFoo(); 

29                    break; 

30                case "bar": 

31                    $obj = new MyBar(); 

32                    break; 

33            } 

34            return $obj; 

35        } 

36 

37        $global_obj = CreateObject ("foo"); 

38        $global_obj->setValue(7); 

39 

40        print "Value is " . $global_obj->getValue() . "\n"; 

41        print "Value is " . $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这