- PHP 从入门到项目实践(超值版)
- 聚慕课教育研发中心
- 2370字
- 2021-03-30 13:30:29
3.6 常见的关键字和方法
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P67_8666.jpg?sign=1734456436-CFWLOxJ7B9sgw5aSB3efBGMwGSS69C6E-0-e1b6bd86759fce01f14cb6d70e1e25ef)
在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=1734456436-v7uyxs6c5KVkJ6Uom3Db3nQzulJO1277-0-238a42e4d52fd0bbe7c8b6d2ff6334a4)
在类中使用final标识的方法,在子类中不可以重写,也不能被覆盖。例如下面代码:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P67_73818.jpg?sign=1734456436-F8MAJQOP390XCfdHyiBZr5QkKaU2Fott-0-0df2b7099cca840d99ae8d39a2498afc)
下面通过一个实例来介绍。在实例中,首先定义一个类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=1734456436-zbnc3ywYh9vL8ee1kxWRMpJoFVjOBECF-0-4848766720bde5ef30d7ed18eab17ee2)
在IE浏览器中输出的结果如下:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P67_73820.jpg?sign=1734456436-HdmhdqsVcNqWTB31M1NKT5P2BSGClhG3-0-fa1942fa2f76ac517f9b4ff1c84a40e9)
含义是不能覆盖最终方法Person::say()。
3.6.2 static关键字
static关键字的作用是将类的成员属性或成员方法标识为静态的。
使用static关键字标识的成员属性和成员方法在类内、类外调用的方法是不一样的。
在类外调用的方式如下:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P68_73821.jpg?sign=1734456436-f45R4qEUGV8xqKNnjiKObfSGIm1epjmB-0-d291368e25af949426b52e25cf6cdd9d)
【例3-13】(实例文件:ch03\Chap3.13.php)在类外调用static关键字标识的成员。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P68_73822.jpg?sign=1734456436-B7TiXHVhGElqrvQuHgd0Z3cn97eSJXan-0-b785bc719810681de2002e0110f63677)
在IE浏览器中运行结果如图3-9所示。
在类内调用方式如下:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P68_73823.jpg?sign=1734456436-JYJvw54dVDHwKX5VbL1qECG3x32KiLuP-0-92bec1337f88fb4b3546d0c6bed31313)
【例3-14】(实例文件:ch03\Chap3.14.php)在类内调用static关键字标识的成员。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P68_73824.jpg?sign=1734456436-9tBc1IpQ1tIQmorAopzfDO75GoqPTMXQ-0-50ec980f5846276462c3cc7369ad2a37)
在IE浏览器中运行结果如图3-10所示。
提示:在使用静态方法时需要注意,在静态方法中只能访问静态成员。因为非静态的成员必须通过对象的引用进行访问,通常是使用$this来完成。而静态的方法,在对象不存在的情况下也可以直接使用类名来访问,没有对象也就没有$this引用,没有$this引用就不能访问类中的非静态成员,但是可以使用类名或者self在非静态方法中访问静态成员。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P69_8886.jpg?sign=1734456436-Me57xOs0lTUZYeLd4rR0IT3l0o8e2dOJ-0-6ef502ccc014bdd39a7e937c98265d42)
图3-9 在类外调用static关键字标识的成员
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P69_8889.jpg?sign=1734456436-3IDrwYH8aM3UBRJ3xZSUWZCoxC2tL5Jl-0-ccec11f5d38f6579d095e41befc95132)
图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=1734456436-VBKDEHrsoyzMVMInKucfIvFlkrAOyAO0-0-7ff5b8d768ba584190d891c5d5dd73ec)
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P69_9045.jpg?sign=1734456436-9fNBzIWhPpnzsfQEx6wXsrSqm3yPWbql-0-0535b080204db59e2ff44fe320e6564a)
图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=1734456436-1NX71nHyDYszpP9K3R35MXmih1K2hhke-0-b53b120294f0e0542ba93acd67a3a685)
在IE浏览器中运行结果如图3-12所示。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P70_9216.jpg?sign=1734456436-f3ZBAnOfhrXr6LxP2bfLNTY9sdYJ0Ljn-0-91497a6fdf77689516e9d1a679828871)
图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=1734456436-5rcnu4HoEzi3f4tLjaqUPF4zquYiW25t-0-9330ce414efd0a9093c3ee0dc141eed8)
【例3-17】(实例文件:ch03\Chap3.17.php)instanceof关键字的应用。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P70_73833.jpg?sign=1734456436-LdUyz1GeAlqW671ZL3QECbEFvTVgRt0y-0-2ae853445d12568a3b3866d2ae88962b)
在IE浏览器中运行结果如图3-13所示。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P71_9289.jpg?sign=1734456436-j5QwWX50GKUYFqAxlZ2GwxeeBFD1cLVG-0-6e60eb0fe0b80ca6592114a6432d26e4)
图3-13 instanceof关键字的应用
3.6.6 克隆对象
在PHP5中,对象的传递方式默认为引用传递,如果想要在内存中生成两个一样的对象或者创建一个对象的副本,这时可以使用“克隆对象”。
克隆对象是通过关键字clone实现的。语法格式如下:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P71_73838.jpg?sign=1734456436-0GlZMsAP88gyBHbSI60fr6cHcWFG1OgN-0-89b658d6a5c16c95698d9b98252dcfab)
用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=1734456436-1wknmONwIDUlJAsmO1QDllqEW0XkbB6N-0-ca789a8fb90f750a66ef6b2c704c705c)
在IE浏览器中运行结果如图3-14所示。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P72_9561.jpg?sign=1734456436-2PPxIF7RdihJy5E04N9s5aFDXyN0gvif-0-32e41a8c64785cdbece721f42ed2da57)
图3-14 克隆对象的应用
3.6.7 类中通用的__toString()方法
将一个对象当作一个字符串使用时,会自动调用__toString()方法,并且在该方法中,可以返回一定的字符串,以表明该对象转换为字符串之后的结果。
注意:如果将一个未定义__toString()方法的对象转换为字符串,会产生致命的错误。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P72_73841.jpg?sign=1734456436-ziq1LB565jVsHdNylwRGG7mkNBFOIrjq-0-7876abcbb32ca2f61f6a7e07cbcfcb50)
【例3-19】(实例文件:ch03\Chap3.19.php)__toString()方法。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P72_73842.jpg?sign=1734456436-3CqIwUTjqKvkbv4mViZCEQlKnc0MMC2x-0-c3e3498b232a1ec25c2eb866e3217d4b)
在IE浏览器中运行的结果为“对象当成字符串时调用”。
3.6.8 __call和__callStatic()方法
在类外部,对象方式调用一个不可访问方法时,__call()会被调用;用静态方式调用一个不可访问方法时,__callStatic()会被调用。__call()和__callStatic()的语法格式如下:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P72_73843.jpg?sign=1734456436-NtoPvTEs0aSKA5pQhw1DPrZL4EwjwNhQ-0-ca154036509658460b6b99a6322d89d0)
其中,$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=1734456436-QL94wfZey6owosJMPWyEUb1Fkyj5gK1w-0-c1c71343fe187080d2fd13422b05b221)
在IE浏览器中运行结果如图3-15所示。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P73_9769.jpg?sign=1734456436-PyKRkOd5DB8dl5ZtjmpbBeQ08Mdk3TXS-0-67f3f1bec732e038907f92a93c3f9376)
图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=1734456436-Brntg8C98xGiyUP88PPmCJ2OPuXSL9zm-0-b8e0b95310ba5d5623fa0cffde8a5106)
test1.php文件中包含一个Test1类,内容如下:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P73_73849.jpg?sign=1734456436-l9XEnsvee9208CQlB7ozZL5UW7v79JVy-0-abc9fc6a634b76cbbfe178307fa8a162)
Chap3.21.php文件的内容如下:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P74_73852.jpg?sign=1734456436-5aIkHNaB0naERhv4NLxvKZPxfQihJhPY-0-991be21752386fe2131cd9d146f9a626)
在IE浏览器中运行结果如图3-16所示。
3.6.10 对象串行化
串行化对象是把对象转化成bytes数据。可以将串行化的数据存储在一个文件里或网络上传输,然后再反串行化还原为原来的数据。串行化对象使用serialize()函数来完成,反串行化对象使用unserialize()函数来完成。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P74_9989.jpg?sign=1734456436-Hgv8dGUpCUV3JBOwDKHP6vZWt1tuzIJm-0-6f94deb1c6a1ed724a84bedeba3e2baa)
图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=1734456436-2RjS4lPlaRibExbOAah0AkKO1HzAQAUn-0-6ac07315f493981fa3ffb514840fd717)
unserialize.php文件:
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P75_73855.jpg?sign=1734456436-8mN6gASq8vsNZoMymjlWeAkpy7xp186y-0-28a4d232b67d959af960ebfc87558716)
在IE浏览器中运行unserialize.php文件,结果如图3-17所示。
![](https://epubservercos.yuewen.com/B097BE/15477656605638806/epubprivate/OEBPS/Images/Figure-P75_10057.jpg?sign=1734456436-w7yKCkWfCPSEzpTl9feSEUnbnttW5Fjs-0-e4094225a2da0c94c66f15ff6ca8106e)
图3-17 对象串行化