您的位置 首页 php

才知道,PHP 对象原来是偶然成功的 // 深入PHP

来自freepik

随着PHP 对对象的支持越来越广泛,以及面向对象的PHP 库和应用程序大量涌现,PHP 中对象的崛起似乎是一个自然而然且不可避免的过程。但事实远非如此。

对象原本并非PHP 项目的核心部分。实际上,PHP 的设计人员曾将对象描述为“后来才想起来要加上的部分”。PHP中的对象究竟经历了怎样的发展过程呢?

起源:PHP/FI

正如我们所知,PHP 最初的原型是Rasmus Lerdorf 使用Perl 开发的两个小工具。PHP 是Personal Homepage Tools 的缩写,表示“个人主页工具”;而FI 则是Form Interpreter 的缩写,表示“表单解释器”。它们结合而成的宏命令可以将SQL 发送到数据库、处理表单并进行流程控制。

在用C 语言重写后,这些工具被赋予了新的名字——PHP/FI 2.0。虽然那个时期的PHP 语言看似和现在不大相同,但本质上没有太大区别。它支持变量、关联数组和函数,但不支持对象。

语法糖:PHP 3

事实上,就算到了PHP 3 的计划阶段,对象也未位列其中。PHP 3 的主要架构师是Zeev Suraski和Andi Gutmans。PHP 3 完全重写了PHP/FI 2.0,但对象并没被视为需要加入的新语法。

根据Zeev Suraski 的回忆,PHP 对类的支持是后来才加上的(准确地说是1997 年8 月27 日)。那时的类和对象实际上是定义和访问关联数组的另外一种方式。

当然,加入了方法和继承的类比关联数组更加强大,但那时对类的操作仍然很局限,特别是无法访问父类中被重写的方法(如果不明白这句话的意思也不必担心,我会在后面解释)。另一个不足之处是下面将讲到的,对象在PHP 脚本之间的传递方式并非最佳。

在这个时期,对象只是边缘话题,官方文档也没有着重指出这些内容。PHP 手册只用了一句话和一段代码来介绍对象,而且这个例子没有提及继承和属性。

一场静悄悄的革命:PHP 4

PHP 4 是PHP 的一个突破性版本,许多核心的改变都发生在这个版本中。Zend 引擎(它的名字由Zeev 中的Ze 和Andi 中的nd 结合而成)的问世为PHP 提供了强大的动力,它是驱动PHP的主要组件之一。任何你可能会调用的PHP 函数,实际上都是高级扩展层的一部分。它们的名字反映了它们所完成的工作,例如与数据库API 进行交互或是与 字符串 打交道。在底层,Zend引擎管理内存、委托对其他组件的控制,并将我们熟知且每天都使用的PHP 语法“翻译”为可执行的字节码。正是因为Zend 引擎,我们才可以使用类等PHP 语言的核心特性。

从面向对象的角度看,PHP 4 给程序员带来的最大便利是可以重写父类的方法并在子类中访问它们。

然而,主要的缺点仍然存在。将对象赋值给一个变量,然后将它传递给函数或是从函数中返回它,都会创建该对象的一个副本。请思考如下两句赋值语句:

$my_obj = new User('bob');
$other = $my_obj;
 

这会导致有两个User 对象存在,而不是指向同一个User 对象的两条引用。大多数面向对象编程语言都是引用赋值,而非传值赋值,这意味着我们可以传递和赋值指向对象的句柄,而不用复制这些对象。PHP 这种默认的值传递的行为会导致许多潜在的bug,因为程序员在修改了脚本某处的对象后,会误认为其他引用也会有这些修改。你将在本书中看到,我在许多例子中都维护了多个指向同一个对象的引用。

幸运的是,还有一种强制引用传递的方式,但它需要使用一种看起来很笨的语法。

下面是一个引用赋值的例子:

$other =& $my_obj;
// $other 和$my_obj 指向同一个对象
 

下面是一个引用传递参数的例子:

function setSchool(& $school)
{
 // $school 现在是被传递进来的对象的引用,而不是它的副本
}
 

下面是一个引用返回的例子:

function & getSchool()
{
 // 返回引用而不是副本
 return $this->school;
}
 

尽管代码也可以正常工作,但在编码过程中,我们其实很容易忘记加上&符号,这就意味着在面向对象的代码中容易滋生bug。而且这些bug 难以跟踪,因为它们不会导致程序出错,只会导致程序的行为与我们预想的不同。

这时的PHP 手册不仅涵盖了语法,还包括了对象方面的内容,而且面向对象编程逐渐成为主流。对象在PHP 中并不是没有引起争论(现在仍然一样),类似“我需要对象吗”的帖子在邮件组的讨论中随处可见。Zend 网站上既有支持面向对象编程的讨论文章,也有持反对意见的文章。尽管引用传递的问题和种种争议依然存在,但许多程序员还是在他们的代码中加上了&符号,使用面向对象方式进行开发。使用PHP 进行面向对象编程逐渐发展起来。Zeev Suraski 在Your Information Source for Enterprise Application Development 上发表的文章中谈到了这一点:

如前面所说,很多网站和文章开始讨论面向对象设计。PHP 的官方软件库PEAR 本身就包含了面向对象编程。虽然有些“事后诸葛亮”,但很容易就能看出,PHP 对面向对象的支持只不过是对无法阻挡的面向对象编程趋势的一种妥协。值得注意的是,尽管面向对象编程诞生于20 世纪60 年代,但它直到20 世纪90 年代中期才得以普及。最为流行的 Java 直到1995 年才发布。作为面向过程的C 语言的超集,C++是在1979 年被设计开发出来的。经过漫长的发展,C++直到20 世纪90 年代才取得了真正的飞跃。Perl 5 于1994 年发布,新的变革使得这个曾经面向过程的语言也开始支持面向对象(虽然有些人认为Perl 对面向对象的支持是后来才想到的)。作为一门小型的面向过程的语言,PHP 迅速实现了对面向对象的支持,这表明了PHP 对用户需求的切实考虑。

拥抱变化:PHP 5

PHP 5 是对对象和面向对象编程的认可。这并不是说对象是PHP 唯一的工作方式。但是对象被认为是开发企业级系统的强大助力和重要方法,而且PHP 在核心设计上也完全支持对象。

随着PHP 5 中功能的增强,越来越多的大型互联网公司开始采用这门语言,例如Yahoo!和Facebook 在其平台上广泛使用PHP。PHP 已经成为互联网开发和互联网企业的标准语言之一。

对象已经从事后的想法变为了PHP 语言发展的驱动力。可能其中最重要的改变就是用默认的引用传递的行为替代了对象复制。但这只是一个开始。我们应该去接触PHP 的更多改进,包括private 和protected 的方法和属性、static 关键字、命名空间、类型提示(现在叫作类型声明)以及异常等。PHP 5 已经发布很长时间了,在此期间不断有重要的新特性面世。

例如,PHP 5.3 带来了命名空间。命名空间允许我们为类和函数创建一个带名字的作用域,这样可以减小在引用其他库或是扩展系统时遇到重名的可能性。同时,命名空间还将我们从下面这样丑陋的命名约定中拯救了出来:

class megaquiz_util_Conf
{
}
 

这样的类名可以防止不同包之间发生类名冲突,但是也会让代码变得很“别扭”。

我们还会看到PHP 对闭包函数、生成器、trait 以及延迟静态绑定的支持。

迎头追赶:PHP 7

但程序员不会因此而满足。对于许多喜爱设计模式的程序员来说,PHP 仍然缺少两个关键特性——标量类型声明和强制返回类型。在PHP 5 中,如果需要一个对象、数组或是稍后可回调的代码,我们都可以强制指定传递给函数或方法的参数的类型,但我们无法强制指定标量值(如整数、字符串和浮点型)的类型,也没有办法声明方法或函数的返回值的类型。

正如你将看到的,面向对象设计经常将方法声明作为一种契约。方法会要求特定的输入,然后返回给你特定的数据类型。使用PHP 5 时,程序员在很多情况下只能依靠注释、约定和手动类型检查来维持这类契约。开发人员和评论员经常抱怨连连。下面的内容引自《深入PHP:面向对象、模式与实践(第3版)》,现已出新版《深入PHP:面向对象、模式与实践(第5版)》。

目前,PHP 开发组仍未就“在PHP 中加入带提示的返回类型”给出任何承诺。带提示的返回类型允许我们在方法或函数声明中声明要返回的对象的类型,而且PHP 引擎将来也会支持它。带提示的返回类型可以进一步提高PHP 对设计原则(如“针对接口编程,而不是针对实现编程”等原则)的支持。希望有一天,我能够在本书中加入有关这个特性的内容。

我很高兴地写道,这一天终于到来了!PHP 7 引入了标量类型声明(也就是之前提到的类型提示)以及返回类型声明。你将看到《深入PHP:面向对象、模式与实践(第5版)》中大量使用了这些新特性。PHP 7 还提供了其他不错的特性,比如匿名类和一些命名空间改进。

拥护和顾虑:关于对象的争辩

对象和面向对象设计引发了两方阵营的激烈争辩。许多优秀的程序员没有使用对象也编写出了优秀的代码,而PHP 仍将是一个杰出的面向过程的Web 编程平台。

本书会自然而然地偏向面向对象,这种偏向反映了作者对面向对象的前景的看法。本书关注对象和面向对象设计,因此会不可避免地强调面向对象。但要注意的是,本书绝非提倡“面向对象是通往PHP 编程的唯一康庄大道”。

“开发人员是否选择将PHP 作为面向对象语言使用”曾经是一个偏好问题,现在仍然是这样,开发人员可以使用函数和全局代码创建可完美运行的系统。一些优秀工具(如WordPress)的基础架构仍然是面向过程的(尽管这些工具可能会广泛地使用对象)。然而,不使用和不理解PHP对对象的支持,PHP 程序员的开发过程将变得越来越艰难,尤其是项目所依赖的第三方库可能是面向对象的情况。

不过,我们应当记住Perl 的那句名言:“做一件事有很多方法。”对于小型脚本来说尤其如此,因为迅速编写一个程序并让其运行起来,远比构建一种易于扩展为大型系统的架构(在极限编程领域中,这类项目被称为spike)更加重要。

代码是一种很灵活的东西,编写代码的秘诀在于必须知道概念验证会在何时成为大型项目开发的基石,并在确定设计方案之前停止大量编码。既然你现在已经决定采用面向对象方式来应对规模不断增长的项目,希望这本书能够为你构建面向对象的架构提供帮助。

文章来源:智云一二三科技

文章标题:才知道,PHP 对象原来是偶然成功的 // 深入PHP

文章地址:https://www.zhihuclub.com/152557.shtml

关于作者: 智云科技

热门文章

网站地图