PHP核心技术与最佳实践(txt+pdf+epub+mobi电子书下载)


发布时间:2020-05-09 19:36:58

点击下载

作者:列旭松,陈文

出版社:机械工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

PHP核心技术与最佳实践

PHP核心技术与最佳实践试读:

前言

为什么要写这本书

近几年,市场上关于PHP的书已经很多了,各种培训机构也如雨后春笋般不断增加。那为什么还要写这本书呢?这本书存在的意义又在哪里?这要从下面的几个问题说起。

有没有这样一本PHP教材,它不讲HTML和CSS,也不讲JavaScript基础,甚至不讲PHP语法基础?

有没有这样一本PHP教材,它不讲留言本或博客的开发,也不讲数据库的CRUD操作?

有没有这样一本PHP教材,它专注于Web开发技术的最前沿,深入浅出,适合中高级程序员的进阶和提高?

有没有这样一本PHP教材,它提倡面向对象的程序思想,提倡算法和数据结构的重要性,提倡对网络协议的深入理解,且没有大篇幅的代码,而是更多偏重于理论讲解?

有没有这样一本PHP教材,它探讨PHP的扩展开发,探讨高并发大流量的架构,深入探讨NoSQL的内部实现和细节?

以上几个问题也是我在早期PHP学习的过程中一直在寻找的答案,可是我并没有找到一本理想的PHP书籍,一本适合中高级程序员进阶的书籍。当怀着同样问题的旭松兄找到我时,我们不禁产生一个念头:“既然现在市场上缺少一本这样的书籍,我们何不自己写一本呢?利己利人的事值得去做。”然后一拍即合,说做就做,现在这本书经历长达一年多的酝酿和写作过程终于完稿了。

我是在大学期间接触到PHP语言的,并马上被其简洁的语法和极高的开发效率所吸引,一头扎进PHP开发的世界中。随着学习的深入,并经常关注PHP社区的动态,我很快意识到一些PHP社区普遍存在的问题。比如PHP社区一直争论算法重不重要,面向对象好不好,代码质量重要还是开发速度重要的问题。还有譬如为什么我去大型互联网公司应聘PHP程序员,却不考察我对PHP语法和函数的掌握情况,而是会问我C语言、算法、网络协议、高并发处理、MVC理论这些看似和PHP不沾边的问题。

PHP到底要怎么学,学什么,一个高级PHP程序员应该是什么样的,我想这也是很多PHP新手和工作一两年的PHP开发者的疑惑。这本书所要解决的就是这一系列的问题。

在我看来,一本技术书籍的价值在于其对知识的提炼和与众不同的地方。举例来说,到一个书店去看书,你最想用笔抄下来或撕下来带走的那几页,就是对你帮助最大的东西,也是你认为这本书的价值所在。也是基于这个想法,我们思考这本书该写什么,怎么写,哪些地方对读者有帮助。我们试图从不同的角度带领读者来看PHP,进而给这本书注入一些不一样的东西。我们希望这是一件有意义的事。本书适合的对象

·PHP爱好者;

·想进阶的初级PHP程序员;

·对PHP扩展开发感兴趣的读者;

·对高并发感兴趣的读者;

·对NoSQL应用和实现原理感兴趣的读者;

·从事PHP网络应用,想知道HTTP协议、Socket等更多细节的开发人员;

·想就职于大型互联网公司的PHP程序员;

·开设相关课程的大专院校的学生;

·公司内部培训的学员。如何阅读本书

本书一共有14章。每章节都可以单独阅读,由于部分知识点之间存在一定的衔接,故建议按先后顺序阅读。

第1章为面向对象思想的核心概念。本章主要讲解面向对象开发的思想,重点讲解面向对象模型的建立,以及面向对象的一些基础概念。通过大量对比和实例,尤其是与Java的对比,力图从不同角度讲解PHP面向对象的特性,让PHP程序员看到不同的面向对象。求同存异是本章的核心思想。

第2章为用面向对象思维写程序。本章用简练的语言讲解了面向对象设计的五大原则,这五大原则也是理解设计模式的基础所在,帮助读者站在一个更高的角度思考面向对象。

第3章为正则表达式技巧与实战。本章详细介绍了正则的基础语法,通过大量的示例、通俗的语言讲解正则概念,引导读者理解正则的一系列规则。接下来,结合实际工作用安全过滤、URL重写等实例,加深对正则的应用和掌握。最后给出正则效率优化的一些普遍技巧和替代方案,让读者对正则的使用得心应手。

第4章为PHP网络技术及应用。本章着重介绍了HTTP协议、Socket开发、WebService、Cookie和Session使用等。结合实战向读者阐述网络开发的核心和重点,特别是对HTTP协议的理解。HTTP协议是Web开发的基石,也是各种面试和开发中必然遇到的知识点。而Socket则是应用交互的桥梁,保证了有用的可扩展性。

第5章为PHP与数据库基础。本章从不同角度分析了MySQL,介绍了PDO、MySQL优化、存储过程、事件调度机制以及MySQL安全防范等内容。

第6章为PHP模板引擎的原理与最佳实践。本章通过实现一个简单的模板引擎,学习模板引擎的原理和使用方法,然后对比几大流行的模板引擎实现方案,简单介绍了各种实现方案的思想和优缺点,最后探讨模板引擎的意义。

第7章为PHP扩展开发。本章的知识是本书核心内容,介绍了PHP扩展开发的几个重要知识点,如扩展框架搭建、PHP生命周期、PHP变量在内核中的实现方式、Zend引擎、内存管理等,让读者深入PHP底层,知其然也知其所以然。

第8章为缓存。本章主要介绍了缓存的基本原理和三个衡量指标,通过几个实例加深读者对缓存的理解。利用本章知识,读者应该能设计一个比较合理的缓存方案。

第9章为Memcached应用与内幕。本章深入剖析了Memcached的实现和内部结构,从而使读者掌握Memcached的高级应用,对构建复杂环境的缓存层有个清晰的认识。

第10章为Redis应用与内幕。本章重点介绍了Redis的深入应用,如事务处理、主从同步、虚拟内存等,和第9章类似,探讨了Redis的实现内幕。合理利用Redis可以为我们解决大流量高并发的应用。

第11章为高性能网站架构。本章探讨了高性能架构的基本出发点,重点以HandlerSocket、MySQL主从复制、反向代理缓存软件Varnish和任务分发框架Gearman为例,讲述几种高性能架构中会用到的技术。

第12章为调试与测试。科学的调试方法有助于快速找出潜在的Bug、理解复杂应用的流程、提高开发效率。单元测试是代码质量的保障。在这一章的最后一节介绍了使用JMeter进行压力测试的方法。

第13章为Hash算法与数据库的实现。本章介绍了Hash算法的基本原理,用此算法实现一个简单的、基于Hash的数据库,让读者意识到算法的重要性和可操作性。

第14章为PHP编码规范。本章介绍了PHP开发中应遵循的基本代码规范,并提出合理建议。好的代码必然是规范的代码。

本书第1、2、3、5、6、8、12、14章由陈文撰写,第7、9、10、11、13章由列旭松撰写,第4章由两人共同完成。勘误和支持

由于我们的水平和开发经验有限,同时计算机技术更新较快,书中难免存在不足之处,有些章节内容可能从未来的某一天开始不再适用,还望读者理解和体谅,并恳请读者批评指正。您若对本书有什么好的建议或者对书中部分内容有疑惑,可与我们联系,我们将尽量为读者提供最满意的解答。期待得到您的真挚反馈。我们的联系方式如下:

陈文:waitfox@qq.com

列旭松:liexusong@qq.com感谢

首先要感谢PHP之父Rasmus Lerdorf,是他创建了这个简单、轻松、有趣、快速而又高效的语言;其次,感谢PHP社区每一位充满活力的朋友,和你们的交流使我学到很多,本书有不少内容就来自于社区的智慧。

在这里尤其要感谢机械工业出版社华章公司的大力支持,特别是杨福川和白宇两位编辑,在一年多的时间里,因为有了你们的耐心指导、逐字逐句认真审稿和改稿才有了本书的诞生。

最后,还要感谢家人和朋友的支持。陈文第1章面向对象思想的核心概念

面向对象是什么?以下是维基百科对面向对象的解释:

面向对象程序设计(Object-Oriented Programming,OOP)是一种程序设计范型,同时也是一种程序开发方法。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和可扩展性。

面向过程、面向对象以及函数式编程被人们称为编程语言中的三大范式(实际上,面向过程与面向对象都同属于命令式编程),是三种不同编码和设计风格。其中面向对象的核心思想是对象、封装、可重用性和可扩展性。

面向对象是一种更高级、更抽象的思维方式,面向过程虽然也是一种抽象,但面向过程是一种基础的抽象,面向对象又是建立在面向过程之上的更高层次的抽象,因此对面向对象的理解也就不是那么容易了。

面向对象和具体的语言无关。在面向对象的世界里,常常提到的两种典型语言——C++和Java。它们都是很好的面向对象的开发语言。实际上,像C语言这种大家普遍认为的面向过程开发的主打语言,也能进行面向对象的开发,就连JavaScript这门很久之前一直被视作面向过程编程的语言,人们对它的认识也发生了改变,逐渐承认其是面向对象的语言,并且也接受了JavaScript独特的面向对象的语法。所以我们说面向对象只是种程序设计的理念,和具体的语言无关。不同的程序员既可以用C语言写出面向对象的风格来,也可以用Java写成面向对象的风格。这里并不是说面向对象的风格要优于面向过程,而是二者各有自己所擅长的领域。OOPL(Object-Oriented Programming Language)可以提高程序的封装性、复用性、可维护性,但仅仅是“可以”,能不能真正实现这些优点,还取决于编程和设计人员。就PHP而言,其不是一门纯的面向对象的语言,但是仍然可以使用PHP写出好的面向对象风格的代码。

实际开发中,面向对象为什么让我们觉得那么难?面向对象究竟难在什么地方?为什么面向对象开发在PHP里一直不是很受重视,并且没有得到普及和推广?PHP对面向对象的支持到底如何?怎么学习面向对象的思维?

在这里,我们将就面向对象一些概念展开讨论,其中重点讨论PHP特色的面向对象的风格和语法,并通过相互借鉴和对比,使读者认识PHP自身的特点,尤其是和其他语言中不同的地方。1.1 面向对象的“形”与“本”

类是对象的抽象组织,对象是类的具体存在。

2200年前的战国时期,赵国平原君的食客公孙龙在骑着白马进城时,被守城官以马不能入城拦下,公孙龙即兴演讲,口述“白马非马”一论,守城官无法反驳,于是公孙龙就骑着他的白马(不是马的)进城去了。这就是历史上最经典的一次对面向对象思维的阐述。

公孙龙的“白马非马”论如下:“白马非马”,可乎?曰:“可。”曰“何哉?”曰:“马者,所以命形也;白者,所以命色也。命色者非命形也。故曰:‘白马非马’。”曰:“有白马不可谓无马也。不可谓无马者,非马也?有白马为有马,白之,非马何也?”曰:“求马,黄、黑马皆可致;求白马,黄、黑马不可致。使白马乃马也,是所求一也。所求一者,白者不异马也。所求不异,如黄、黑马有可有不可,何也?可与不可,其相非明。故黄、黑马一也,而可以应有马,而不可以应有白马,是白马之非马,审矣!”

公孙龙乃战国时期的“名家”,名家的中心论题是所谓“名”(概念)和“实”(存在)的逻辑关系问题。名者,抽象也,类也。实者,具体也,对象也。从这个角度讲,公孙龙是我国早期的最著名的面向对象思维的思想家。“白马非马”这一论断的关键就在于“非”字,公孙龙一再强调白马与马的特征,通过把白马和马视为两个不同的类,用“非”这一关系,成功地把“白马”与“马”的关系由从属关系转移到“白马”这个对象与“马”这个对象的相等关系上,显然,二者不等,故“白马非马”。而我们正常的思维是,马是一个类,白马是马这个类的一个对象,二者属于从属关系。说“白马非马”,就是割裂马与白马之间的从属关系,偷换概念,故为诡辩也。

白马非马这个典故,我们可以称之为诡辩。但我们把这个问题抽象出来,实际上讨论的就是类与类之间的界定、类的定义等一系列问题,类应该抽象到什么程度,其中即涉及了类与对象的本质问题,也涉及了类的设计过程中的一些原则。1.1.1 对象的“形”

要回答类与对象本质这个问题,我想可以先从“形”的角度来回答。本节以PHP为例,来探讨对象的“形”与“本”的问题。

类是我们对一组对象的描述。

在PHP里,每个类的定义都以关键字class开头,后面跟着类名,紧接着一对花括号,里面包含有类成员和方法的定义。如下面代码所示:

在这里,我们定义了一个person类。代表了抽象出来的人这个概念,它含有姓名和性别这两个属性,还具有一个开口说话的方法,这个方法会告诉外界这个人的性别和姓名。我们接下来就可以产生这个类的实例:

这段代码则实例化了person类,产生了一个student对象和teacher对象的实例。实际上也就是从抽象到具体的过程。现实世界中,仅仅说“人”是没有意义的,中国人把它叫“人”,美国人把它叫person或者human,如果高兴,把它叫“God”或者“板凳”都无所谓。但是只要你把“人”这个概念加上各种属性和方法,比如说有两条腿、直立行走、会说话,则无论是中国人,还是美国人,甚至外星人都是能理解你所描述的事物。所以,一个类的设计需要能充分展示其最重要的属性和方法,并且能与其他事物相区分。只有类本身有意义,从抽象到具体的实例化才会有意义。

根据上面的实例代码,可以有下面的一些理解:

·类定义了一系列的属性和方法,并提供了实际的操作细节,这些方法可以用来对属性进行加工。

·对象含有类属性的具体值,这就是类的实例化。正是由于属性的不同,才能区分不同的对象。在上面例子里,由于student和teacher的性别和姓名不一样,才得以区分开二人。

·类与对象的关系类似一种服务与被服务、加工与被加工的关系,具体而言,就如同原材料与流水线的关系。只需要在对象上调用类中所存在的方法,就可以对类的属性进行加工,并且展示其功能。

类是属性和方法的集合,那么在PHP里,对象是什么呢?比较普遍的说法就是“对象由属性和方法组成”。对象是由属性组成,这很好理解,一个对象的属性是它区别于另一个对象的关键所在。由于PHP的对象是用数组来模拟的,因此我们把对象转为数组,就能看到这个对象所拥有的属性了。

继续使用上面代码,可以打印student对象:

到这里,可以很直观地认识到,对象就是一堆数据。既然如此,可以把一个对象存储起来,以便需要时用。这就是对象的序列化。

所谓序列化,就是把保存在内存中的各种对象状态(属性)保存起来,并且在需要时可以还原出来。下面的代码实现了把内存中的对象当前状态保存到一个文件中:

输出序列化后的结果:

在需要时,反序列化取出这个对象:

注意 在序列化和反序列化时都需要包含类的对象的定义,不然有可能出现在反序列化对象时,找不到该对象的类的定义,而返回不正确的结果。

可以看到,对象序列化后,存储的只是对象的属性。类是由属性和方法组成的,而对象则是属性的集合,由同一个类生成的不同对象,拥有各自不同的属性,但共享了类的代码空间中方法区域的代码。1.1.2 对象的“本”

我们需要更深入地了解这种机制,看对象的“本”。对象是什么?对象在PHP中也是变量的一种,所以先看PHP源码中对变量的定义:图1-1 对象的组成

zvalue_value,就是PHP底层的变量类型,zend_object_value obj就是变量中的一个结构。接着看对象的底层实现。

在PHP5中,对象在底层的实现是采取“属性数组+方法数组”来实现的。可以简单地理解为PHP对象在底层的存储如图1-1所示。

对象在PHP中是使用一种zend_object_value结构体来存储的。对象在ZEND(PHP底层引擎,类似Java的JVM)中的定义如下:

ce是存储该对象的类结构,在对象初始化时保存了类的入口,相当于类指针的作用。properties是一个HashTable,用来存放对象属性。guards用来阻止递归调用。

类的标准方法在zend/zend_object_handlers.h文件中定义,具体实现则是在zend/zend_object_handlers.c文件中。关于PHP变量的存储结构的底层实现,将在第7章中进行更深入的介绍。

通过对上述源代码的简单阅读,可以更清晰地认识到对象也是一种很普通的变量,不同的是其携带了对象的属性和类的入口。1.1.3 对象与数组

对象是什么,我们不好理解,也不容易回答,但是我们知道数组是什么。数组的概念比较简单。可以拿数组和对象对比来帮助我们理解对象。对象转化为数组,数组也能转换成对象。数组是由键值对数据组成的,数组的键值对和对象的属性/属性值对十分相似。对象序列化后和数组序列化后的结果是惊人的相似。如下面的代码所示:

输出为:

可以很清楚地看出,对象和数组在内容上一模一样!

而对象和数组的区别在于:对象还有个指针,指向了它所属的类。在对student对象序列化时,我们看到了“person”这几个字符,这个标识符就标志了这个对象归属于person类,故在取出这个对象后,可以立即对其执行所包含的方法。如果对象中还包含对象呢?我们来看下一节的内容。1.1.4 对象与类

在前面代码中定义了一个类,并创建了这个类的对象,把前面产生的对象作为这个新对象的一个属性,完整代码如代码清单1-1所示。

代码清单1-1 object.php

输出结果如下:

可以看出,序列化后的对象会附带所属的类名,这个类名保证此对象能够在执行类的方法(也是自己所能执行的方法)时,可以正确地找到方法所在的代码空间(即对象所拥有的方法存储在类里)。另外,当一个对象的实例变量引用其他对象时,序列化该对象时也会对引用对象进行序列化。

基于如上的分析,可以总结出对象和类的概念以及二者之间的关系:

·类是定义一系列属性和操作的模板,而对象则把属性进行具体化,然后交给类处理。

·对象就是数据,对象本身不包含方法。但是对象有一个“指针”指向一个类,这个类里可以有方法。

·方法描述不同属性所导致的不同表现。

·类和对象是不可分割的,有对象就必定有一个类和其对应,否则这个对象也就成了没有亲人的孩子(但有一个特殊情况存在,就是由标量进行强制类型转换的object,没有一个类和它对应。此时,PHP中一个称为“孤儿”的stdClass类就会收留这个对象)。

理解了以上四个概念,结合现实世界从实现和存储理解对象和类,这样就不会把二者看成一个抽象、神秘的东西,也就能写出符合现实世界的类了。

如果需要一个类,要从客观世界抽象出一套规律,就得总结这类事物的共性,并且让它可以与其他类进行区分。而这个区分的依据就是属性和方法。区分的办法就是实例化出一个对象,是骡子是马,拉出来遛遛。

现在,你是否对“白马非马”这个典故有了新的认识?1.2 魔术方法的应用

魔术方法是以两个下画线“___”开头、具有特殊作用的一些方法,可以看做PHP的“语法糖”。语法糖指那些没有给计算机语言添加新功能,而只是对人类来说更“甜蜜”的语法。语法糖往往给程序员提供了更实用的编码方式或者一些技巧性的用法,有益于更好的编码风格,使代码更易读。不过其并没有给语言添加什么新东西。PHP里的引用、SPL等都属于语法糖。

实际上,在1.1节代码中就涉及魔术方法的使用。family类中的___construct方法就是一个标准魔术方法。这个魔术方法又称构造方法。具有构造方法的类会在每次创建对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。因此,这个方法往往用于类进行初始化时执行一些初始化操作,如给属性赋值、连接数据库等。

以代码清单1-1所示代码为例,family中的___construct方法主要做的事情就是在创建对象的同时对属性赋值。也可以这么使用:

这样做就不需要在创建对象后再去赋值了。有构造方法就有对应的析构方法,即___destruct方法,析构方法会在某个对象的所有引用都被删除,或者当对象被显式销毁时执行。这两个方法是常见也是最有用的魔术方法。1.2.1 _set和_get方法

___set和___get是两个比较重要的魔术方法,如代码清单1-2所示。

代码清单1-2 magic.php

运行这段代码会怎样呢?结果报错如下:

所报错误大致是说,不能访问Account对象的私有属性user。在代码清单1-2的类定义里增加以下代码,其中使用了___set魔术方法。

再次运行,看到正常输出,没有报错。在类里以两个下画线开头的方法都属于魔术方法(除非是你自定义的),它们是PHP中的内置方法,有特殊含义。手册里把这两个方法归到重载。

PHP的重载和Java等语言的重载不同。Java里,重载指一个类中可以定义参数列表不同但名字相同的多个方法。比如,Java也有构造函数,Java允许有多个构造函数,只要保证方法签名不一样就行;而PHP则在一个类中只允许有一个构造函数。

PHP提供的“重载”指动态地“创建”类属性和方法。因此,___set和___get方法被归到重载里。

这里可以直观看到,若类中定义了___set和___get这一对魔术方法,那么当给对象属性赋值或者取值时,即使这个属性不存在,也不会报错,一定程度上增强了程序的健壮性。

我们注意到,在account类里,user属性的访问权限是私有的,私有属性意味着这个属性是类的“私有财产”,只能在类内部对其进行操作。如果没有___set这个魔术方法,直接在类的外部对属性进行赋值操作是会报错的,只能通过在类中定义一个public的方法,然后在类外调用这个公开的方法进行属性读写操作。

现在有了这两个魔术方法,是不是对私有属性的操作变得更方便了呢?实际上,并没有什么奇怪的,因为这两个方法本身就是public的。它们和在对外的public方法中操作private属性的原理一样。只不过这对魔术方法使其操作更简单,不需要显式地调用一个public的方法,因为这对魔术方法在操作类变量时是自动调用的。当然,也可以把类属性定义成public的,这样就可以随意在类的外部进行读写。不过,如果只是为了方便,类属性在任意时候都定义成public权限显然是不合适的,也不符合面向对象的设计思想。1.2.2 _call和_callStatic方法

如何防止调用不存在的方法而出错?一样的道理,使用___call魔术重载方法。

___call方法原型如下:

当调用一个不可访问的方法(如未定义,或者不可见)时,___call()会被调用。其中$name参数是要调用的方法名称。$arguments参数是一个数组,包含着要传递给方法的参数,如下所示:

以上代码模拟了类似其他语言中的根据参数类型进行重载。跟___call方法配套的魔术方法是___callStatic。当然,使用魔术方法“防止调用不存在的方法而报错”,并不是魔术方法的本意。实际上,魔术方法使方法的动态创建变为可能,这在MVC等框架设计中是很有用的语法。假设一个控制器调用了不存在的方法,那么只要定义了___call魔术方法,就能友好地处理这种情况。

试着理解代码清单1-3所示代码。这段代码通过使用___callStatic这一魔术方法进行方法的动态创建和延迟绑定,实现一个简单的ORM模型。

代码清单1-3 simpleOrm.php

再举个类似的例子。PHP里有很多字符串函数,假如要先过滤字符串首尾的空格,再求出字符串的长度,一般会这么写:

如果要实现JS里的链式操作,比如像下面这样,应该怎么实现?

很简单,先实现一个String类,对这个类的对象调用方法进行处理时,触发___call魔术方法,接着执行call_user_func即可。1.2.3 _toString方法

再看另外一个魔术方法___TOstring(在这里故意这么写,是要说明PHP中方法不区分大小写,但实际开发中还需要注意规范)。

当进行测试时,需要知道是否得出正确的数据。比如打印一个对象时,看看这个对象都有哪些属性,其值是什么,如果类定义了___toString方法,就能在测试时,echo打印对象体,对象就会自动调用它所属类定义的___toString方法,格式化输出这个对象所包含的数据。如果没有这个方法,那么echo一个对象将报错,例如“Catchable fatal error:Object of class Account could not be converted to string”语法错误,实际上这是一个类型匹配失败错误。不过仍然可以用print_r()和var_dump()函数输出一个对象。当然,___toString是可以定制的,所提供的信息和样式更丰富,如代码清单1-4所示。

代码清单1-4 magic_2.php

运行这段代码发现,使用___toString方法后,输出的结果是可定制的,更易于理解。实际上,PHP的___toString魔术方法的设计原型来源于Java。Java中也有这么一个方法,而且在Java中,这个方法被大量使用,对于调试程序比较方便。实际上,___toString方法也是一种序列化,我们知道PHP自带serialize/unserialize也是进行序列化的,但是这组函数序列化时会产生一些无用信息,如属性字符串长度,造成存储空间的无谓浪费。因此,可以实现自己的序列化和反序列化方法,或者json_encode/json_decode也是一个不错的选择

为什么直接echo一个对象就会报语法错误,而如果这个对象实现___toString方法后就可以直接输出呢?原因很简单,echo本来可以打印一个对象,而且也实现了这个接口,但是PHP对其做了个限制,只有实现toString后才允许使用。从下面的PHP源代码里可以得到验证:

由此可见,魔术方法并不神奇。

有比较才有认知。最后,针对本节代码给出一个Java版本的代码,供各位读者用来对比两种语言中重载和魔术方法的异同,如代码清单1-5所示。

代码清单1-5 Account.java

运行上述代码,输出如图1-2所示。图1-2 Java里的构造方法和重载演示

可以看出,Java的构造方法比PHP好用,PHP由于有了___set/___get这一对魔术方法,使得动态增加对象的属性字段变得很方便,而对Java来说,要实现类似的效果,就不得不借助反射API或直接修改编译后字节码的方式来实现。这体现了动态语言的优势,简单、灵活。

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载