这是一篇翻译文章,申明,不是我翻译的,我不翻译文章,我只是文章的搬运工(仿某广告)
原文是IBM网上某作者的英文版,在这里,是风之缘网站的一篇转载(是我从他网上转载啦)
PHP V5和面向对象编程
2004年PHP V5发布,和PHP V4相比,它在面向对象编程(OOP)和设计方面有了巨大的进步,增加了一些必要的特性,如类的可见性、正确的构造函数与析构函数、类型提示和类反射 API。PHP5为高级面向对象编程开启了方便之门,使得开发者可以更简单地实现各种设计模式,设计出更好的类和API。
在PHP V5.3中,继续大幅加强OOP能力,这些改进包括语法的进化和性能的改善等方面。首先让我们来看静态方法和属性相关的新特性。
改进后的静态方法与属性的处理方式
PHP V5中一个实用的新增特性是可以指定类的一个方法或属性为静态成员(PHP V4支持静态地访问类的方法和属性,但是无法指定它们是为静态访问而设计的)。静态访问在实现单例模式时非常有用,此时,类只存在一个实例。
PHP V5.3增加了若干特性,以加强对类的静态方法和属性的支持。首先,我们来分析新增的魔术方法:__callStatic()。
__callStatic()魔术方法
PHP V5包含了若干个可以用于类内部的魔术方法。如果在类中定义了这些方法,它们可以提供特殊的功能,从而实现重载(允许一个方法接收不同类型的参数)和多态 (允许不同数据类型使用相同的接口)功能。同时,它们也让PHP中的面向对象编程(OOP)和设计模式的实现变得更加简单。
在PHP V5.3中,新增了一个魔术方法:__callStatic()。它和
__call()魔术方法类似,后者用于处理类中不存在或不可见的方法调用。而
__callStatic()用于处理类似的静态方法调用,方便开发者实现方法的重载。下面是一个如何使用的例子。
Listing 1. Example of using __callStatic()
vs. __call()
- class Foo
- {
- public static function __callStatic(
- $name,
- $args
- )
- {
- echo "Called method $name statically";
- }
- public function __call(
- $name,
- $args
- )
- {
- echo "Called method $name";
- }
- }
- Foo::dog(); // 输出"Called method dog statically"
- $foo = new Foo;
- $foo->dog(); // 输出"Called method dog"
__callStatic()方法必须是
public,而且是static。类似的,__call()魔术方法也要求定义为
public,其实所有的魔术方法都要求定义为public。
动态的静态调用
PHP中有一个实用的特性是变量的变量。它意味着你可以用一个变量的字符串值作为另外一个变量的名字。换句话说,你可以完成下面的功能。
Listing 2. Variable variables
- x = 'y';
- $$x = 'z';
- echo $x; // 输出'y'
- echo $$x; // 输出'z'
同样的概念可以用于函数,甚至类的成员函数,如下例所示。
Listing 3. Variable function and class method names
- class Dog
- {
- public function bark()
- {
- echo "Woof!";
- }
- }
- $class = 'Dog'
- $action = 'bark';
- $x = new $class(); // 实例化类'Dog'
- $x->$action(); // 输出"Woof!"
Listing 4. Variable class naming
- class Dog
- {
- public static function bark()
- {
- echo "Woof!";
- }
- }
- $class = 'Dog';
- $action = 'bark';
- $class::$action(); //输出"Woof!"
接下来让我们关注另外一个更加实用的关于静态方法和属性方面的功能改善:静态调用的晚绑定。
静态调用的晚绑定(膘叔:是否叫后绑定或者延迟绑定较好?)
PHP V5.3之前一个令人恼火的事情是静态方法和属性的处理。到目前为止,静态引用,包括使用self或__CLASS__,都是在函数定义所在类的范围内解析。当继承一个类,并在子类中调用静态函数时,将会发生解析错误。PHP V5.3中新增的静态调用晚绑定特性解决了这个问题。为了更好的说明这个问题,我们创建如下一个包含静态方法的类。
Listing 5. ClassFoo
with static method test()
|
- class Foo
- {
- protected static $name = 'Foo';
- public static function test()
- {
- return self::$name;
- }
- }
Listing 6. Child class
Bar
that extends parent class Foo
- class Bar extends Foo
- {
- protected static $name = 'Bar';
- }
Listing 7. Static method call
test()
这个调用的输出将是字符串
Foo。因为test()方法中的
self::$name引用是在
Foo这个类中解析。而PHP解释器这么做是因为test()方法是在类Foo中定义的。
PHP V5.3通过使用static关键字,使得该引用可以在当前类中解析。将上面的类Foo改写为如下定义(译注:注意红色部分),输出将变为Bar。
Listing 8. Using the static keyword
- class Foo
- {
- protected static $name = 'Foo';
- public static function test()
- {
- return static::$name;
- }
- }
- class Bar extends Foo
- {
- protected static $name = 'Bar';
- }
- echo Bar::test(); // 输出'Bar'
在分析了一些有关静态方法和属性方面的改善之后,我们来看看PHP V5中非常重要的部分:标准PHP库中新增的一些类。
标准PHP库
PHP V5中新增的标准PHP库是用于解决标准问题的一组类和接口。这些问题包括可迭代对象、数组对象和链表等。使用这些类和接口的好处是:它们是PHP的原生 方法,比用PHP实现的效率要高。 同时,它们使得许多PHP内置函数和语言结构可以直接使用这些对象,比如你可以通过foreach结构遍历一个实现了迭代器接口的对象。
PHP V5.3在SPL中增加了若干个类。如早前提到过的双向链表SplDoublyLinkedList。SPL中新增的栈和队列类:SplStack和SplQueue的实现中都使用了该类。
下面看一下如何使用SplStack
类实现一个栈。
Listing 9. Using SplStack
SplMinHeap、
SplMaxHeap
和SplPriorityQueue)。
另外新增的一个实用类是SplFixedArray,如名字暗示的那样,它是一个固定大小的数组实现。不过,它的速度比PHP内置的数组要快20-30%,原因是它是固定大小的,而内置数组是变长的,并且它只允许数字索引。下面演示了它的用法。
SplFixedArray
- $array = new SplFixedArray(3);
- $array[0] = 'dog';
- $array[1] = 'cat';
- $array[2] = 'bird';
- $a->setSize(4); // increase the size on the fly
- $array[3] = 'mouse';
- foreach ( $array as $value )
- echo "[$value],";
- Output:
- [dog],[cat],[bird],[mouse]
FilesystemIterator
和GlobIterator。它们的行为与PHP中的其它迭代器一致,只不过它们是为特定目的而定制的。
另外一个变化是SPL在PHP V5.3中将强制启用。以前的PHP V5版本,你可以在编译的时候禁止SPL,但是这个选项现在没有了。
SPL的改善提高了PHP的易用性,并实现了数据结构如双向链表、栈、堆和队列等。它们可以替换用户自己实现的这些数据结构,这样不但可以提高效率,而且还可以促进PHP函数和语言结构的整合。
讨论完SPL的改进之后,我们看看PHP V5.3如何通过采用循环垃圾回收技术来提高OOP的性能与内存消耗。
循环垃圾回收
PHP开发者经常碰到的一个性能瓶颈是垃圾回收。PHP有一个非常简单的垃圾回收器,用于回收不在作用域内的对象。它的原理是通过引用计数,当计数到达0时(意味着不再有引用指向该对象),该对象被回收,释放占用的内存。
这种方式简单高效,但是在父子关系的对象引用中会产生问题。此时,这些对象的引用计数器不为0,所以不会被回收,一直存在到请求的结束。下面我们来看这个问题的一个例子。
Listing 11. Parent-child class relationship not properly garbage collected in PHP V5.2 and earlier
- class Parent
- {
- public function __construct()
- {
- $this->child = new Child($this);
- }
- }
- class Child
- {
- public function __construct(
- Parent $parent
- )
- {
- $this->parent = $parent;
- }
- }
- for ($i = 0; $i < 1000; $i++) {
- new Parent();
- }
在PHP V5.3中,垃圾回收器将会检测这种循环引用并释放它们,从而使该脚本的内存使用保持在正常状态。当Parent对象的引用计数为0时,Parent内部引用的Child对象也将被回收。
总结
PHP在支持面向对象编程方面走过了漫漫长路,从PHP V4时的弱支持到PHP V5中的飞跃以及后续版本的改进。现在PHP V5.3又加入了一些令人兴奋的改进,包括语法上的改进,如新的__callStatic() 魔术方法、动态的静态调用、静态调用的晚绑定和静态方法和属性的支持。SPL上则增加了双向链表、栈、堆和队列的实现,为开发者提供了现成的常用数据结构 并提高它们的易用性。最后,期盼已久的循环垃圾回收器修复了自引用类导致的内存和性能问题,通过这个大幅改进的垃圾回收器,正确释放循环引用的对象。上述 的特性,让
PHP V5.3成为一个更强大的面向对象编程语言。
原文链接:http://www.ibm.com/developerworks/opensource/library/os-php-5.3new1/index.html