![PHP 从入门到项目实践(超值版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/705/27111705/b_27111705.jpg)
3.6 常见的关键字和方法
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P67_8666.jpg?sign=1734475329-iUaxmFgnE4Mnw0NWOw45YAu1va4mJcy0-0-71ac56f50a49db442b2c667a49d3cd8a)
在PHP中有很多的关键字,用来修饰类的属性和方法,如public、protected、static、private等。
3.6.1 final关键字
final关键字是PHP 5新增的。如果父类中的方法被声明为final,则子类无法覆盖该方法。如果一个类被声明为final,则不能被继承。
注意:属性不能被定义为final,只有类和方法才能被定义为final。
使用final标识的类,不能再被继承,也不能再有子类。例如下面代码:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P67_73817.jpg?sign=1734475329-s2oDd4ximpLfPywXaYiXDWEsSEnnjvFO-0-2184f2f74df83f211e75ccba250ddfff)
在类中使用final标识的方法,在子类中不可以重写,也不能被覆盖。例如下面代码:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P67_73818.jpg?sign=1734475329-KcYzMB1lw5NNjMcQ5tGjvkJOK0kBQpc7-0-5395a89348c4381fd43cee46f21690db)
下面通过一个实例来介绍。在实例中,首先定义一个类Person,在类中定义一个say()方法,在前面加上final关键字;然后定义一个子类Man,在这个子类中覆盖父类中的say()方法。
【例3-12】(实例文件:ch03\Chap3.12.php)final关键字的应用。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P67_73819.jpg?sign=1734475329-9PlYUgt9amzz7MpzQWG7bdM8avjWXgLs-0-c8b3e6b6a0363da19c993b9f1ede558c)
在IE浏览器中输出的结果如下:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P67_73820.jpg?sign=1734475329-2ApRgZ1K7vtc8cjDHd735aqHwFeNhWKr-0-2cee91619c3a32ab37de984a99d62fc4)
含义是不能覆盖最终方法Person::say()。
3.6.2 static关键字
static关键字的作用是将类的成员属性或成员方法标识为静态的。
使用static关键字标识的成员属性和成员方法在类内、类外调用的方法是不一样的。
在类外调用的方式如下:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P68_73821.jpg?sign=1734475329-HBFAu7PMfyOsQkQ9GKDbqVxOYeDKNEKH-0-9e52ab204ba5f0c8d3d060073aa66233)
【例3-13】(实例文件:ch03\Chap3.13.php)在类外调用static关键字标识的成员。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P68_73822.jpg?sign=1734475329-rXkYVHSteVRwRbcRE2sL5YnvUEu12dw9-0-7bb35d634e4f2fab7d00a98fab504201)
在IE浏览器中运行结果如图3-9所示。
在类内调用方式如下:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P68_73823.jpg?sign=1734475329-bD12gqzLJ2BsipdjWbbPe8fRHUsvKppR-0-e69c6ba7dc7c14353d28d3b2143cdd7b)
【例3-14】(实例文件:ch03\Chap3.14.php)在类内调用static关键字标识的成员。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P68_73824.jpg?sign=1734475329-nwaUEtmujjLxk66I9e8SPJh8Ow0CwAvT-0-65028ea0d1d38a0eb2de26414a0c50d8)
在IE浏览器中运行结果如图3-10所示。
提示:在使用静态方法时需要注意,在静态方法中只能访问静态成员。因为非静态的成员必须通过对象的引用进行访问,通常是使用$this来完成。而静态的方法,在对象不存在的情况下也可以直接使用类名来访问,没有对象也就没有$this引用,没有$this引用就不能访问类中的非静态成员,但是可以使用类名或者self在非静态方法中访问静态成员。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P69_8886.jpg?sign=1734475329-P2SZVObNbv5vyyMiJ0kabAqRisMffsBZ-0-cdd0bda6dc1cad2fc443ffb4aef05c07)
图3-9 在类外调用static关键字标识的成员
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P69_8889.jpg?sign=1734475329-PzHY9V8NNBLMZphR9w1S2gauaamDue4u-0-28e590a5d74a9b17e392fa3c641a4b7a)
图3-10 在类内调用static关键字标识的成员
3.6.3 单态设计模式
单态设计模式就是让类的一个对象成为系统中的唯一实例,避免大量的new操作而消耗内存资源,也方便设置钩子输出日志信息等。
实现单态设计模式需要满足以下三点:
(1)一个私有的静态的属性:用于保存仅有的一个实例化对象。
(2)一个私有的构造方法:确保用户无法通过创建对象对其进行实例化。
(3)一个公有的静态的方法:负责对其本身进行实例化。
【例3-15】(实例文件:ch03\Chap3.15.php)实现单态设计模式。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P69_73827.jpg?sign=1734475329-Ao0iT08R2xsQ0u7ZaAiJsi8H14i56t63-0-aadb07f32d5cc400bb362f18d0b0a6df)
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P69_9045.jpg?sign=1734475329-OvI6aDNQZxNT8zkCiE86DRnt98gA6eq4-0-aa09cb4089122bd7940d2ba669159139)
图3-11 实现单态设计模式
在IE浏览器中运行结果如图3-11所示。
从例3-15的结果可以发现,不管调用类的实例多少次,只实例化一次Example类。
3.6.4 const关键字
const是一个定义常量的关键字。调用const常量的方式和静态成员(static)的调用是一样的,在类外通过类名访问,在成员方法中使用self关键字进行访问。具体参考3.6.2节。
注意:const标识的常量是一个恒值,不能重新赋值,所以一定要在定义的时候初始化。使用const声明的常量名称前不能使用$符号,并且常量名通常都是大写的。
【例3-16】(实例文件:ch03\Chap3.16.php)const关键字的应用。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P70_73831.jpg?sign=1734475329-nRVcJer27OcYmUR94Kqk4aorNM04jCNj-0-8746eb524037436c6e2d14ca5d6cd541)
在IE浏览器中运行结果如图3-12所示。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P70_9216.jpg?sign=1734475329-h4frB1LQC5FqiGdI0oP4IgSHRxifuwy4-0-57169d5b0ce5f0313c4b347bda4a5f92)
图3-12 const关键字的应用
3.6.5 instanceof关键字
instanceof关键字有以下两个用法:
(1)判断一个对象是否是某个类的实例。
(2)判断一个对象是否实现了某个接口。
本节主要介绍第一个用法。使用instanceof关键字判断一个对象是某个类的实例时,返回true;否则返回false。
instanceof关键字语法格式如下:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P70_73832.jpg?sign=1734475329-JBIH4wQonfEDtKztuqNdaLdPwbGapUo7-0-820bcc4d3fdb392eeadffe6010dccc09)
【例3-17】(实例文件:ch03\Chap3.17.php)instanceof关键字的应用。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P70_73833.jpg?sign=1734475329-IeP3MG2ulifC58vT8APVhBKxkh7CKfoy-0-9a095841666fdb777e29df41c998380b)
在IE浏览器中运行结果如图3-13所示。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P71_9289.jpg?sign=1734475329-fsZQuO0b4xcJJJfrnvFVHCAi3uAHi8yw-0-822f16d6c20465cc69ea9a027a67c840)
图3-13 instanceof关键字的应用
3.6.6 克隆对象
在PHP5中,对象的传递方式默认为引用传递,如果想要在内存中生成两个一样的对象或者创建一个对象的副本,这时可以使用“克隆对象”。
克隆对象是通过关键字clone实现的。语法格式如下:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P71_73838.jpg?sign=1734475329-TE22O7rp46gvWvfNOYKM8OgzseOrlscX-0-083f416e52846d66239a6a26d6e5a50a)
用clone克隆出来的对象与原对象没有任何关系,它是把原来的对象从当前的位置重新复制了一份,也就是相当于在内存中新开辟了一块空间。
克隆对象时,PHP会检查克隆的原对象中是否含有__clone()方法,如果不存在,就会调用默认的__clone()方法,复制对象的所有属性;如果__clone()方法已经定义过,那么__clone()方法就会执行定义的内容。
【例3-18】(实例文件:ch03\Chap3.18.php)克隆对象的应用。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P71_73839.jpg?sign=1734475329-Qaa3ZrhCRhm10y8PzWwJV8Sk3m0anHU4-0-00d658659b3f39edd5413fbf21ef7494)
在IE浏览器中运行结果如图3-14所示。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P72_9561.jpg?sign=1734475329-lvnCMlW1nvflBa0S1Xk7SCOfcEstzLWs-0-49cc2684c23c04c70ca8b849a897e245)
图3-14 克隆对象的应用
3.6.7 类中通用的__toString()方法
将一个对象当作一个字符串使用时,会自动调用__toString()方法,并且在该方法中,可以返回一定的字符串,以表明该对象转换为字符串之后的结果。
注意:如果将一个未定义__toString()方法的对象转换为字符串,会产生致命的错误。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P72_73841.jpg?sign=1734475329-gyKhoj5e1BEMyxxVd3uNx7zAkco6vFnQ-0-b1780ff7810e4798f722870ffab86c27)
【例3-19】(实例文件:ch03\Chap3.19.php)__toString()方法。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P72_73842.jpg?sign=1734475329-F7wbSnTfyxlfC3F3waAdJdSVd70X078k-0-af17809029dd29f46a2b8c4aeb5edf14)
在IE浏览器中运行的结果为“对象当成字符串时调用”。
3.6.8 __call和__callStatic()方法
在类外部,对象方式调用一个不可访问方法时,__call()会被调用;用静态方式调用一个不可访问方法时,__callStatic()会被调用。__call()和__callStatic()的语法格式如下:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P72_73843.jpg?sign=1734475329-CSLNmmviZjLqDc51eqtKeJTZNtk0HoTh-0-4f80013d8254a51d61d0a48ded7851ee)
其中,$name参数是要调用的方法名称;$arguments参数是一个枚举数组,包含着要传递给$name方法的参数。
【例3-20】(实例文件:ch03\Chap3.20.php)__call()和__callStatic()方法的应用。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P72_73844.jpg?sign=1734475329-8Xew3Z3jDWZfMdcDEHxjMrVbvr1dwKQK-0-a639d68a1963c336301c382d515367ff)
在IE浏览器中运行结果如图3-15所示。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P73_9769.jpg?sign=1734475329-hu3M9DEiefLKKbNgKEHwBgg8HjL6VjOE-0-1804fa391e5361ab0b45dcbbc54f51d0)
图3-15 __call()和__callStatic()方法的应用
3.6.9 自动加载类
在编写面向对象的应用程序时,有时要引用某个类或类的方法,需要使用include或者require导入到文件才能使用。每用一个类就需要写一条include的语句,这样是很烦的一件事。
在PHP5中,可以定义一个__autoload()函数,它会在试图使用尚未被定义的类时自动调用。
下面通过一个实例进行介绍。
【例3-21】(实例文件:ch03\Chap3.21.php)自动加载类。
创建test.php和test1.php两个文件。
test.php文件中包含一个Test类,内容如下:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P73_73848.jpg?sign=1734475329-D4jW19OVg1rfyv2cpDSHfj5Er8SMfctP-0-e44d697b4c9d75f3d4e82800f825c0f0)
test1.php文件中包含一个Test1类,内容如下:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P73_73849.jpg?sign=1734475329-GFAZKHVwatKzleFeYFHDLWOpEBYBoNaN-0-c5b56b62f505261dd15d6a5eea1e2fd7)
Chap3.21.php文件的内容如下:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P74_73852.jpg?sign=1734475329-CJOoqSbNUZpEn8uY4K1aAm8EZxwA938Y-0-fe828da05851652a95e9e971b7c1cdf2)
在IE浏览器中运行结果如图3-16所示。
3.6.10 对象串行化
串行化对象是把对象转化成bytes数据。可以将串行化的数据存储在一个文件里或网络上传输,然后再反串行化还原为原来的数据。串行化对象使用serialize()函数来完成,反串行化对象使用unserialize()函数来完成。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P74_9989.jpg?sign=1734475329-91IoYjGa4QgWhWFNwKC0N7VgOEcWeitP-0-b25d309b1e9f0bded75cee75e350bdc0)
图3-16 自动加载类
在执行串行化对象时,PHP会首先检查是否存在一个魔术方法__sleep(),如果存在,会先调用__sleep()方法。__sleep()方法可以用于清理对象,并返回一个包含对象中所有变量名称的数组。在执行反串行化对象时,PHP会检查是否存在一个__wakeup()方法,如果存在,则会先调用__wakeup()方法,预先准备对象数据。
这两个方法都不接受参数。__sleep()方法必须返回一个数组,包含需要串行化的属性。如果没有__sleep()方法,PHP将保存所有属性。
【例3-22】(实例文件:ch03\Chap3.22.php)对象串行化。
Chap3.22.php文件如下:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P74_73851.jpg?sign=1734475329-H7wGCJvQyLAP78uC7r7kr8t1CCH9KMrD-0-ec13d067d59e511a1c73d8e629ac406e)
unserialize.php文件:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P75_73855.jpg?sign=1734475329-NdtplP12MTzT1edawUDxlDxAlo0LJG0e-0-cf2b55ac95a14e65747084e2ff890fd3)
在IE浏览器中运行unserialize.php文件,结果如图3-17所示。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P75_10057.jpg?sign=1734475329-CACCxrTsRqns9Oa4sqNUdCV4aQak3eTG-0-b7dee0c568532f5c8a801a001af7e819)
图3-17 对象串行化