使用 PHP V5 的新语言特性,可以明显地提高代码的可维护性和可靠性。通过阅读本文,您将了解如何利用这些新特性将用 PHP V4 开发的代码迁移到 PHP V5。
PHP V5 在 PHP V4 基础上做了重大改进。新语言特性使构建可靠的类库和维护类库更加容易。另外,重写标准库帮助使 PHP 更符合其同一 Web 语系,例如 Java™ 编程语言。让我们来看一些 PHP 新的面向对象特性,并了解如何将现有 PHP V4 代码迁移到 PHP V5。
首先,先来了解新语言特性及 PHP 的创建程序怎样更改了用 PHP V4 创建对象的方法。用 V5 的想法是要创建一种工业级语言用于 Web 应用程序开发。那意味着要了解 PHP V4 的限制,然后从其他语言中 (例如 Java、C#、C++、Ruby 和 Perl 语言) 抽取已知优秀语言架构并将这些架构并入 PHP 中。
第一个也是最重要的新特性是针对类的方法和实例变量的访问保护 —— public、protected 和 private 关键字。 这个新特性使类设计人员可以保证对类的内在特性的控制,同时告诉类的使用者哪些类可以而哪些类不可以触及。
在 PHP V4 中,所有代码都是 public 的。在 PHP V5 中,类设计人员可以声明哪些代码是对外部可见的 (public) 而哪些代码仅对类内部可见 (private) 或仅对类的子类可见 (protected)。如果没有这些访问控制,则在大型团队中开发代码或将代码分布为库的工作会受阻,因为那些类的使用者很可能使用错误的方法或访问应当为 private 成员变量的代码。
另一个较大的新功能是关键字 interface 和 abstract,这两个关键字允许进行契约编程。契约编程 意味着一个类向另一个类提供一张契约 —— 换言之: “这是我要做的工作,你不需要知道它是怎样完成的”。 实现 interface 的所有类都遵循该契约。interface 的所有使用者都同意仅使用 interface 中指定的方法。abstract 关键字使得使用接口十分容易,我稍后将加以说明。
这两个主要特性 —— 访问控制和契约编程 —— 允许大型编码人员团队更顺畅地使用大型代码库。这些特性还使 IDE 可以提供更丰富的语言智能特性集。本文不但说明了若干个迁移问题,而且还花了一些时间说明如何使用这些新主要语言特性。
访问控制
为了演示新语言特性,我使用了一个名为 Configuration 的类。这个简单的类中含有用于 Web 应用程序的配置项 —— 例如,指向图片目录的路径。在理想的情况下,此信息将驻存在一个文件或数据库里。清单 1 显示了一个简化的版本。
清单 1. access.php4
<?php
class Configuration
{
var $_items = array();
function Configuration() {
$this->_items[ 'imgpath' ] = 'images';
}
function get( $key ) {
return $this->_items[ $key ];
}
}
$c = new Configuration();
echo( $c->get( 'imgpath' )."\n" );
?>
这是一个完全正统的 PHP V4 类。成员变量保存配置项的列表,构造程序装入项,然后名为 get() 的访问方法返回项的值。
运行脚本后,以下代码将显示在命令行中:
% php access.php4
images
%
很好!这个结果意味着代码运行正常并且正常设定和读取了 imgpath 配置项的值。
将这个类转换为 PHP V5 的第一步是要将构造程序重命名。在 PHP V5 中,初始化对象 (构造程序) 的方法称为 __construct。这次小改动如下所示。
清单 2. access1.php5
<?php
class Configuration
{
var $_items = array();
function __construct() {
$this->_items[ 'imgpath' ] = 'images';
}
function get( $key ) {
return $this->_items[ $key ];
}
}
$c = new Configuration();
echo( $c->get( 'imgpath' )."\n" );
?>
这次改动并不大。只是移至 PHP V5 约定。下一步是添加对类的访问控制以确保类的使用者无法直接读写 $_items 成员变量。这次改动如下所示。
清单 3. access2.php5
<?php
class Configuration
{
private $_items = array();
public function __construct() {
$this->_items[ 'imgpath' ] = 'images';
}
public function get( $key ) {
return $this->_items[ $key ];
}
}
$c = new Configuration();
echo( $c->get( 'imgpath' )."\n" );
?>
如果这个对象的使用者都要直接访问项阵列,访问将被拒绝,因为该阵列被标记为 private。幸运的是,使用者发现 get() 方法可以提供广受欢迎的读取权限。
为了说明如何使用 protected 权限,我需要另一个类,该类必须继承自 Configuration 类。我把那个类称为 DBConfiguration,并假定该类将从数据库中读取配置值。此设置如下所示。