PHP V5.3 中的新特性,第 1 部分: 对象接口的变化

简介: PHP V5 和面向对象编程 与 PHP V4 提供的特性相比,2004 年发布的 PHP V5 在面向对象编程(OOP)和设计方面向前迈出了很大的一步。它提供了一些必要的改进,例如类可见性、合适的构造函数和解构函数、输入提示和类反射(class-reflection)API。

PHP V5 和面向对象编程

与 PHP V4 提供的特性相比,2004 年发布的 PHP V5 在面向对象编程(OOP)和设计方面向前迈出了很大的一步。它提供了一些必要的改进,例如类可见性、合适的构造函数和解构函数、输入提示和类反射(class-reflection)API。它为在 PHP 中进行高级的面向对象编程敞开了大门,并允许实现更加简单的设计模式,以及更好的设计类和 API。

PHP V5.3 在 OOP 方面提供了大量渐进式补充。这些改进一直集中在语法补充和性能改进方面。首先,我们将查看静态方法和成员方面的新特性。

 

回页首

改进静态方法和成员处理

PHP V5 中的一个有用补充就是能够将一个方法或类成员指定为静态的(PHP V4 确实支持对方法和类成员的静态访问,但是不能够将方法或成员指定为专门用于静态访问)。静态访问特别适合实现单一设计模式,在这种模式中只存在一个类实例。

PHP V5.3 提供一些特性来增强对类的静态成员和方法的支持。我们将查看最近添加的一种魔术方法:__callStatic()

_callStatic() 魔术方法

PHP V5 提供了一些可用于类内部的特别定义的方法,称为魔术方法。当在类内部定义时,这些方法可以提供特殊的功能,并支持重载(允许一种方法接受不同类型的参数)和多态(允许不同数据类型使用相同的接口)。它们还允许通过 PHP 轻松地使用不同类型的 OOP 编程方法和设计模式。

在 PHP V5.3 中,添加了一种新的魔术方法:__callStatic()。它的工作方式类似于 __call() 魔术方法,后者的设计意图是处理那些没有在类中定义或对类不可见的方法的调用。然而,__callStatic() 是为了处理静态方法调用,这使我们能够更好地设计方法重载。下面给出了一个使用该方法的示例。


清单 1. 使用 __callStatic() 和 __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();       // outputs "Called method dog statically" 
$foo = new Foo; 
$foo->dog();      // outputs "Called method dog" 

 

需要注意,PHP 确实加强了对 __callStatic() 方法的定义;它必须是公共的,并且必须被声明为静态的。同样,__call() 魔术方法必须被定义为公共的,所有其他魔术方法都必须如此。

 

回页首

动态的静态调用

PHP 的一个优秀特性是可变变量。这表示可以使用某个变量的字符串值指定另一个变量的名称。换句话说,可以执行与下面类似的操作。


清单 2. 可变变量

				
x = 'y'; 
$$x = 'z'; 
echo $x;  // outputs 'y' 
echo $$x; // 
outputs 'z' 

 

这也适用于函数,甚至是类方法,如下所示。


清单 3. 可变函数和类方法名

				 
class Dog 
{ 
    public function bark() 
    { 
        echo "Woof!"; 
    } 
} 

$class = 'Dog' 
$action = 'bark'; 
$x = new $class(); // instantiates the class 'Dog' 
$x->$action();     // outputs "Woof!" 

 

PHP V5.3 的一个新特性就是在进行静态调用时,能够使指定的类名成为一个变量。这提供了一些新的机会,如下所示。


清单 4. 可变的类命名

				 
class Dog 
{ 
    public static function bark() 
    { 
         echo "Woof!"; 
    } 
} 

$class = 'Dog'; 
$action = 'bark'; 
$class::$action();  //outputs "Woof!" 

 

这一补充完善了 PHP 的可变变量特性,允许将它们应用到涉及 PHP 的所有情形。

让我们查看一个有关静态方法和成员应用的更有用的增强:延迟静态绑定(late static binding)。

 

回页首

延迟静态绑定

在 V5.3 以前,PHP 存在的麻烦问题是如何处理静态方法和成员。到目前为止,使用自身或 __CLASS__ 进行的静态引用都是在定义函数的类作用域中解析的。问题在于,如果类进行了扩展并且调用来自新的子类,那么解析将是错误的。PHP V5.3 添加了延迟静态绑定来解决这个问题。为了更好地进行解释,我们在下面将创建一个具有静态方法的类。


清单 5. 使用静态方法 test() 的 Foo 类

				 
class Foo 
{ 
    protected static $name = 'Foo'; 

    public static function test() 
    { 
        return self::$name; 
    } 
} 

 

让我们对这个类进行扩展。我们将在子类中重新定义成员 $name


清单 6. 子类 Bar 扩展了父类 Foo

				 
class Bar 
{ 
    protected static $name = 'Bar'; 
} 

 

我们在清单 7 中进行了静态调用。


清单 7. 静态方法调用 test()

				 
echo Bar::test(); 

 

该调用的输出是字符串 Foo。这是因为在 test() 方法中进行的引用 self::$name 是在 Foo 类中完成的。这样绑定的原因是:函数是在Foo 类中定义的。

PHP V5.3 添加了关键字 static 以允许针对当前类进行引用。因此将修改上面的 Foo 类以在清单 8 中使用该关键字,我们将看到输出的内容变成了 Bar


清单 8. 使用 static 关键字

				 
class Foo 
{ 
    protected static $name = 'Foo'; 

    public static function test() 
    { 
        return static::$name; 
    } 
} 

class Bar 
{ 
    protected static $name = 'Bar'; 
} 

echo Bar::test(); // outputs 'Bar'

 

有关 static 关键字需要注意一点,它的工作方式与在非静态上下文中的工作方式不同。这意味着普通的继承规则没有应用到静态调用中。静态关键字将仅仅尝试在当前类中解析调用,而不是在定义函数的类中执行。这一点值得注意。

现在您已经了解了有关静态方法和成员的增强,现在让我们看一看 PHP V5 中新添的类,它们构成了非常有用的部分:标准 PHP 库。

 

回页首

标准 PHP 库

标准 PHP 库(Standard PHP Library,SPL)是 PHP V5 中新增的接口和类的集合,旨在解决标准问题。这些问题包括实现可迭代的对象,使对象具有数组的行为或实现一个链接的列表。这些类和方法的优点是它们是原生的 PHP,这意味用 PHP 本身实现它们会获得更快的速度。在很多情况下,这些类和方法还允许内部 PHP 函数直接使用这些对象,就像 Iterator 接口允许您使用 foreach 结构迭代对象一样。

PHP V5.3 向 SPL 添加了更多的类。我们前面提到一个类就是在 SPL 类 SplDoublyLinkedList 中实现的双重链接列表。它供其他两个新 SPL 类使用:SplStack(实现一个栈)和 SplQueue(实现一个队列)。

让我们看一看如何使用 SplStack 类实现一个栈。


清单 9. 使用 SplStack

				
$stack = new SplStack(); 

// push a few new items on the stack 
$stack->push('a'); 
$stack->push('b'); 
$stack->push('c'); 

// see how many items are on the stack 
echo count($stack); // returns 3 

// iterate over the items in the stack 
foreach ( $stack as $item ) 
    echo "[$item],";   
// the above outputs: [c],[b],[a]

// pop an item off the stack 
echo $stack->pop(); // returns 'c' 

// now see how many items are on the stack 
echo count($stack); // returns 2

 

SqlQueue 也采取类似的方式,但是它像队列那样工作(先进先出;而不是像栈一样最后一个项进栈,第一个项出栈)。此外,还存在堆实现(SplHeap),以及针对某些情况的特定队列和堆实现(SplMinHeapSplMaxHeap 和 SplPriorityQueue)。

另一个有用的补充是 SplFixedArray 类,顾名思义,这是一个固定大小的数组实现。然而,它的性能非常快 — 实际上它在基准测试中要比 PHP 内置数组实现快 10% 至 30%。造成这种速度优势的原因是数组是固定大小的,而默认的 PHP 数组是可变大小的,并且不允许非数值型索引。清单 10 显示了它的使用方法。


清单 10. 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 通常启用 SPL。在以前的 PHP V5 版本中,可以在编译时禁用 SPL,但是 PHP V5.3 不能禁用 SPL。

SPL 中的新补充?? PHP 添加了一些有用的并且易于使用的功能,以及数据结构的实现,例如双重链接列表、栈、堆和队列。这些类可用于替换用户空间实现,这将改进速度并更好地集成各种 PHP 函数和构造。

现在我们已经了解了 SPL 中的一些新内容,让我们看一看 PHP V5.3 中的 OOP 如何通过循环垃圾收集获得显著的性能和内存使用改善。

 

回页首

循环垃圾收集

垃圾收集是 PHP 开发人员在性能方面遇到的一个问题。PHP 有一个非常简单的垃圾收集器,它实际上将对不再位于内存范围(scope)中的对象进行垃圾收集。垃圾收集的内部方式是使用一个引用计数器,因此当计数器达到 0 时(意味着对该对象的引用都不可用),对象将被当作垃圾收集并从内存中删除。

这种方式工作得很好,但是如果一个对象使用父子关系引用另一个对象,那就会引发问题。在这种情况下,这些对象的引用计数器没有被收集,因此这些对象使用的内存仍然属于未引用的内存,并且直到完成请求后才能够进行分配。下面看一下关于这种问题的例子。


清单 11. PHP V5.2 及之前版本不能恰当地对父子类关系进行垃圾收集

				
class Parent 
{ 
    public function __construct() 
    { 
        $this->child = new Child($this); 
    } 
} 

class Child 
{ 
    public function __construct( 
        Parent $parent 
        ) 
    { 
        $this->parent = $parent; 
    } 
} 

 

在这种情况下,每当创建 Parent 类的实例并且该实例随后超出内存范围时,内存不会被释放,因此脚本在内存使用中不断增加。有一些用户空间解决方案可以解决这个问题。例如为父类创建一个解构函数将直接释放子对象。这种解构器必须在解除父类引用之前进行调用。但是执行这些工作会使您的代码也变得非常复杂。

在 PHP V5.3 中,垃圾收集器将检测这些循环引用,并且能够释放它们所占用的内存,因此在执行脚本时 PHP 内存使用情况将保持平稳。当 Parent 类的每个引用被删除后,Parent 类中的 Child 类引用也将会被当作垃圾收集。

 

回页首

结束语

PHP 在支持面向对象编程方面经历了长期的发展。PHP V4 时期的支持是比较弱的,但在 PHP V5 中得到显著的改善,并且后续版本还会调整。现在,PHP V5.3 提供了一些令人兴奋的改进,包括语法增强,例如新 __callStatic() 魔术方法、动态的静态调用、延迟静态绑定、静态方法和成员支持。它为 SPL 添加了新的内容,包括双重链接表、栈、堆和队列的实现,使您获得了一些常见的数据结构并且可以轻松使用它们。最后,期待已久的循环垃圾收集器是一个经过改进的垃圾收集器,它恰当地为这些循环实例释放内存,解决了自引用类的内存和性能问题。所有这些特性使 PHP V5.3 成为一种更加强大的面向对象编程语言。

目录
相关文章
|
2月前
|
缓存 安全 PHP
PHP中的魔术方法与对象序列化
本文将深入探讨PHP中的魔术方法,特别是与对象序列化和反序列化相关的__sleep()和__wakeup()方法。通过实例解析,帮助读者理解如何在实际应用中有效利用这些魔术方法,提高开发效率和代码质量。
|
2月前
|
SQL 安全 PHP
PHP 自发布以来一直在 Web 开发领域占据重要地位,PHP 8 更是带来了属性、刚性类型等新特性。
【10月更文挑战第1天】PHP 自问世以来,凭借其易用性和灵活性,在 Web 开发领域迅速崛起。从简单的网页脚本语言逐步演进为支持面向对象编程的现代语言,尤其自 PHP 5.3 引入命名空间后,代码组织和维护变得更加高效。PHP 7 的性能优化和 PHP 8 的新特性(如属性和刚性类型)进一步巩固了其地位。框架如 Laravel、Symfony、Yii2 和 CodeIgniter 等简化了开发流程,提高了效率和安全性。
52 2
|
3月前
|
PHP 开发者
PHP 7新特性深度解析与实践应用
【9月更文挑战第17天】本文将深入探讨PHP 7的新特性及其对开发者的实际影响,同时通过实例演示如何有效利用这些特性优化代码和提高性能。我们将从类型声明的增强开始,逐步深入到其他关键改进点,最后通过一个综合案例展示如何将这些新特性应用于日常开发中。
|
14天前
|
PHP
PHP中如何比较两个对象
在 PHP 中,比较两个对象可依据状态(属性值)或身份(内存地址)。常用方法包括:1. 使用 `==` 比较属性值;2. 使用 `===` 比较身份和属性;3. 实现 `__equals()` 方法自定义比较逻辑;4. 使用 `spl_object_hash()` 比较对象身份;5. 手动比较属性。选择方法依需求而定。
|
13天前
|
缓存 PHP 开发者
PHP 7新特性及其影响
本文主要介绍了PHP 7的新特性以及这些新特性对开发者和项目的影响。文章详细解析了PHP 7的性能提升、类型声明、空合并运算符等新特性,并讨论了如何利用这些新特性来优化代码。同时,文章也探讨了这些新特性可能带来的问题和挑战,如兼容性问题和学习成本等。最后,文章以一个实际的代码示例来展示如何使用PHP 7的新特性来优化代码。
17 1
|
19天前
|
编译器 PHP 开发者
PHP 8新特性解析与实战应用####
随着PHP 8的发布,这一经典编程语言迎来了诸多令人瞩目的新特性和性能优化。本文将深入探讨PHP 8中的几个关键新功能,包括命名参数、JIT编译器、新的字符串处理函数以及错误处理改进等。通过实际代码示例,展示如何在现有项目中有效利用这些新特性来提升代码的可读性、维护性和执行效率。无论你是PHP新手还是经验丰富的开发者,本文都将为你提供实用的技术洞察和最佳实践指导。 ####
27 1
|
28天前
|
PHP 开发者
PHP 7新特性深度解析
【10月更文挑战第40天】随着PHP 7的发布,这个广泛使用的语言带来了许多令人兴奋的新特性和性能改进。本文将深入探讨PHP 7的主要变化,包括类型声明、错误处理机制、性能优化等方面,帮助开发者更好地理解和应用这些新特性。
32 4
|
1月前
|
PHP 开发者
PHP 7新特性深度解析及其最佳实践
【10月更文挑战第31天】本文将深入探讨PHP 7带来的革新,从性能提升到语法改进,再到错误处理机制的变革。我们将通过实际代码示例,展示如何高效利用这些新特性来编写更加健壮和高效的PHP应用。无论你是PHP新手还是资深开发者,这篇文章都将为你打开一扇窗,让你看到PHP 7的强大之处。
|
1月前
|
安全 编译器 PHP
PHP 8新特性解析与实践应用####
————探索PHP 8的创新功能及其在现代Web开发中的实际应用
|
2月前
|
PHP 数据安全/隐私保护 开发者
PHP 7新特性解析与实践
【10月更文挑战第20天】本文将深入浅出地介绍PHP 7的新特性,包括性能提升、语法改进等方面。我们将通过实际代码示例,展示如何利用这些新特性优化现有项目,提高开发效率。无论你是PHP新手还是资深开发者,都能从中获得启发和帮助。