1. PHP对象的高级应用
final关键字 final的含义是“最终的”“最后的”;被final修饰过的类和方法就是“最终版本”; 如果有一个方法的格式为:
final class class name{
}
说明该类不再被继承,也不能有子类; 如果有一个方法的格式为:
final function method name()
说明该方法在子类中不能进行重写,也不能被覆盖; 例子: 为Employee类设置关键字final,并生成子类MyEmployee,
<?php
final class Employee{
function __construct(){
echo "Employee类";
}
}
class MyEmployee extends Employee{
static function work(){
echo 'MyEmployee子类';
}
}
MyEmployee::work();
?>
2. 抽象类
抽象类是一种不能被实例化的类,只能作为其他的父类使用; 抽象类使用abstract关键字来声明,格式为:
abstract class AbstractName{
}
抽象类和普通类相似,包括成员变量和成员方法;区别在于:抽象类至少要包含并重写某些特定的方法; 例子: 实现动物抽象类Animal,其中包含抽象方法eat();
<?php
abstract class Animal{
abstract function eat();
}
class Dog extends Animal{
function eat()
{
echo "狗喜欢吃骨头!";
}
}
class Cat extends Animal{
function eat()
{
echo "猫喜欢吃鱼!";
}
}
$dog = new Dog();
$cat = new Cat();
$dog -> eat();
echo "<br>";
$cat ->eat();
?>
执行结果如下所示:
3. 接口的使用
继承特性简化了对象、类的创建,增加了代码的可重用性; PHP只支持单继承,若想实现多继承,要使用到接口;PHP能实现多个接口; 接口通过interface关键字声明,并且接口中包含未实现的方法和一些成员变量,格式如下:
interface InterfaceName{
function interfaceName1();
function interfaceName2();
...
}
不用public 外的关键字来修饰接口中的类成员,对于方法,不写关键字也行;由接口自身的属性决定; 子类是通过implements关键字 来实现接口的,若要实现多个接口,每个接口之间要用逗号隔开; 接口中所有未实现的方法都需要在子类中全部实现,否则PHP户出现错误; 格式如下:
<?php
class itfClass implements InterfaceName1,InterfaceName2{
function InterfaceName1(){
...
}
function InterfaceName2(){
...
}
}
...
?>
例子: 声明两个接口Dogs和Animal,接着声明两个子类Dog和Huskie,其中Dog类继承了Dogs接口,Huskie类继承了Dogs和Animal接口;分别实现各自成员变量方法后,实例化两个对象$dog和$huskie ;再调用实现后的方法;
<?php
interface Animal{
function eat();
}
interface Dogs{
function play();
}
class Dog implements Dogs{
function play()
{
echo "一只小狗与人类玩耍!";
}
}
class Huskie implements Dogs,Animal{
function play()
{
echo "一只哈士奇狗不与人类玩耍!";
}
function eat()
{
echo "哈士奇什么都吃!";
}
}
$dog = new Dog();
$huskic = new Huskie();
$dog -> play();
echo "<br>";
$huskic ->play();
$huskic ->eat();
?>
执行结果如下所示:
抽象类和接口实现的功能非常相似;抽象类的优点在抽象类中实现公共方法,接口则能实现多重继承;
4. 克隆对象
1. 克隆对象
对象被当做普通的数据类型时使用;若想引用对象,要使用“&"来声明,不然PHP会按照默认的方式来按值传递对象; 例子: 实例化对象Employee类的对象传递给对象
e
m
p
1
,
emp1,
emp1,emp1的默认值为王某,再将对象
e
m
p
1
,
使
用
普
通
数
据
类
型
的
赋
值
方
式
赋
值
给
对
象
emp1,使用普通数据类型的赋值方式赋值给对象
emp1,使用普通数据类型的赋值方式赋值给对象emp2,改变
e
m
p
2
的
值
为
谢
某
,
再
输
出
对
象
emp2的值为谢某,再输出对象
emp2的值为谢某,再输出对象emp1的值;
php
<?php
class Employee{
private $name='王某';
public function setName($name){
$this ->name = $name;
}
public function getName(){
return $this ->name;
}
}
$emp1 = new Employee();
$emp2 = $emp1;
echo "对象\$emp1的值为:".$emp1 -> getName();
?>
执行结果如下所示
2. __clone()方法
除了单纯的克隆外,有时候还要克隆对象拥有自己的属性和方法,可用__clone()方法 实现; __clone() 的作用是:克隆对象的过程中,调用__clone()方法 ,能使克隆出来的对象保持自己的一些方法和属性; 例子: 在类Employee中创建__clone()方法 ,该方法实现的功能是将变量$name 的默认从王某改为谢某;使对象$emp1 克隆出对象$emp2 ,输出$emp1 和$emp2 的$name 的值;
<?php
class Employee{
private $name='王某';
public function setName($name){
$this -> name = $name;
}
public function getName(){
return $this -> name;
}
public function __clone(){
$this -> name ='谢某';
}
}
$emp1 = new Employee();
$emp2 = clone $emp1;
echo "对象\$emp1的值为:".$emp1 -> getName();
echo "<br>";
echo "对象\$emp2的值为:".$emp2 -> getName();
?>
执行结果如下所示:
5. 比较对象
在开发过程中,要判断两个对象之间的关系是克隆还是引用,用比较运算符 “==” 和 “===” ;两个等号是比较对象的内容,三个等号是比较对象的引用地址; 例子: 实例化对象$emp ,再分别创建克隆对象和引用,使用 “==” 和 “===” 判断它们之间的关系;
<?php
class Employee{
private $name;
function __construct($name){
$this -> name = $name;
}
}
$emp = new Employee('王某');
$cloneemp = clone $emp;
$emp1 = $emp;
if($cloneemp==$emp){
echo "两个对象的内容相同<br>";
}
if($emp1===$emp){
echo '两个对象的引用地址相同';
}
?>
执行结果如下所示:
6. 检测对象类型
instanceof 操作符能检测当前对象属于哪个类; 格式为:
ObjectName instanceofClassName
例子: 创建两个——基类Employee与子类Animal;实例化一个子类对象,判断该对象是否属于这个子类,再判断该对象是否属于这个基类;
<?php
class Employee{}
class Animal extends Employee{
private $type;
}
$animal = new Animal();
if($animal instanceof Animal){
echo "对象\$animal属于Animal类"."<br>";
}
if($animal instanceof Employee){
echo "对象\$animal属于Employee类"."<br>";
}
?>
执行结果如下所示:
7. 魔术方法(__)
PHP中保留了所有以“__" 开头的方法,只能使用PHP中已有的方法,不能自己创建;
1. __set()和__get()方法
两个魔术方法的作用分别为:
- 当程序尝试写入不存在或不可见的成员变量时,PHP会执行
__set()方法 ;__set()方法 包含两个参数,分别表示变量名和变量值;参数不可省略 ; - 当程序调用未定义的成员变量是,能通过
__get()方法 来读取变量值,__get()方法 有一个参数,表示要调用的变量名;
魔术方法,必须在类中进行定义才能使用,PHP不会执行未定义的魔术方法; 例子: 声明类Employee,在该类中创建一个私有变量KaTeX parse error: Expected group after '_' at position 14: type和两个魔术方法——_?_set()和__get();…emp,先对已存在的私有变量进行赋值和调用,再对未声明的变量 $name`进行调用;
<?php
class Employee{
public $type='';
private function __get($name)
{
if(isset($this -> $name)){
echo "\$name值为:".$this -> $name."<br>";
}else{
echo "变量\$name未定义,初始值为0<br>";
$this -> $name = 0;
}
}
}
$emp = new Employee();
$emp->type="Emp";
$emp->type;
$emp->name;
class Employee{
public function work(){
echo "work方法存在!<br>";
}
public function __call($method,$parameter){
echo "方法不存在,执行__call()<br>";
echo "方法名:".$method."<br>";
echo "参数为:";
var_dump($parameter);
}
}
$emp = new Employee();
$emp->work();
$emp->wor('王某',22,'南京');
?>
2. __call()方法
__call()方法 的作用是: 当程序试图调用不能存在或不可见的成员方法时,PHP会先调用方法来存储方法名及其参数; __call()方法包含两个参数,方法名和方法参数; 方法参数是以数组的形式存在; 例子: 声明类Employee,该类包含两个方法——work()和play(),实例化对象$emp 需要调用两个方法:一个是类中存在的work()方法,另一个是不存在的wor()方法;
<?php
class Employee{
public function work(){
echo "work()方法存在!<br>";
}
public function __call($method, $prameter)
{
echo "方法名不存在,执行__call()<br>";
echo "方法名:".$method."<br>";
echo "参数为:";
var_dump($prameter);
}
}
$emp = new Employee();
$emp->work();
$emp-wor('王',33,'南京');
?>
执行结果如下所示:
3. __sleep()和__wakeup()方法
PHP使用serialize()函数 能实例化对象,即将对象中的变量全部保存下来,对象中的类则只保存类名; 在使用serialize()函数 时,若实例化对象包含__sleep() 方法,先执行__sleep() 方法; 该方法能清除对象并返回一个包含该对象中所有变量的数组; 使用__sleep() 方法的目的是关闭对象可能具有的类似数据库连接数据库后等善后操作; unserialize()函数 能重新还原serialize()函数 序列化的对象,__wakeup()方法 则恢复在序列化中可能丢失的数据连接及相关工作; 例子: 声明类Employee,该类中有两个方法——__sleep()和__wakeup() ;实例化对象$emp ,使用serialize()函数 将对象序列化为一个子串$i ,最后使用serialize()函数 将子串$i还原成一个新对象;
<?php
class Employee{
private $name="王某";
public function getName(){
return $this->name;
}
public function __sleep(){
echo "使用serialize()函数,将对象保存起来,能存放在本地或数据库中";
return array('name');
}
public function __wakeup(){
echo "使用该数据时,用unserialize()函数对已经序列化的字符串进行操作,转换回对象";
}
}
$div = new Employee();
$i=serialize($div);
echo '序列化之后的字符串'.$i."<br>";
$emp1 = unserialize($i);
echo '还原后的成员变量为:'.$emp1->getName();
?>
执行结果如下所示:
4. __toString()方法
魔术方法__toString() 的作用是:当使用echo或print 输出对象时,将对象转换为字符串; 例子: 输出类Employee的对象$emp,输出内容为__toString()方法返回的内容;
<?php
class Employee{
private $type="Emp";
public function __toString(){
return $this->type;
}
}
$emp = new Employee();
echo "对象\$emp的值为:".$emp;
?>
执行结果如下所示:
注意: 若没有__toString()方法 ,直接输出对象将会发生致命错误(fatal error) ; 输出对象时应注意,echo或print 后面直接跟要输出的对象,中间不要加对于的字符,否则__toString()方法 不会被执行;
5. __autoload()方法
__autoload()方法 能自动实例化需要使用类; 例子: 创建类文件Employee.class.php;文件中包含类Employee,在创建index.php文件,在文件中创建__autoload()方法,手动实现查找功能,若查找成功,使用include_once()函数将文件动态引入; Employee.class.php类文件
<?php
class Employee{
private $name;
public function __construct($name){
$this->name=$name;
}
public function __toString(){
return $this->name;
}
}
?>
index.php文件
<?php
function __autoload($class_name){
$class_path = $class_name.'Employee.class.php';
if(file_exists($class_path)){
include_once($class_path);
}else{
echo "类路径错误";
}
}
$emp = new Employee("谢某");
echo $emp;
?>
执行结果不是预期的结果:
8. 面向对象的应用——中文字符串的截取类
例子: 编写MysubStr类,定义mysubstr()方法,实现对中文字符串的截取,避免在截取中文字符串时出现乱码问题;
<?php
class MsubStr{
function csubstr($str,$start,$len){
$strlen=$str+$len;
for($i=0;$i<$strlen;$i++){
if(ord(substr($str,$i,1))>0xa0){
$tmpstr=substr($str,$i,2);
$i++;
}else{
$tmpstr=substr($str,$i,1);
}
}
return $tmpstr;
}
}
$mc = new MsubStr();
?>
<table>
<tr>
<td>
<?php
$strs="PHP是一门通用,开源的脚本语言";
if(strlen($str)>10){
echo substr($str,0,9)."...";
}else{
echo $str;
}
?>
</td>
</tr>
<tr>
<td>
<?php
$strs="语法吸收了C,java和Perl语言的特点";
if(strlen($strs)>10){
echo substr($strs,0,9)."...";
}else{
echo $strs;
}
?>
</td>
</tr>
</table>
执行结果如下所示:
结束语
若这篇文章有帮到你,给个赞,收个藏,欢迎大家留言评论; 若文章有什么错误,欢迎大家指教。
|