PHP面向对象程序设计之构造方法和析构方法详解


Posted in PHP onJune 13, 2019

本文实例讲述了PHP面向对象程序设计之构造方法和析构方法。分享给大家供大家参考,具体如下:

构造方法和析构方法是对象中的两个特殊方法,它们都与对象的生命周期有关。构造方法是对象创建完成后第一个被对象自动调用的方法,这是我们在对象中使用构造方法的原因。而析构方法是对象在销毁之前最后一个被对象自动调用的方法,这也是我们在对象中使用析构方法的原因。所以通常使用构造方法完成一些对象的初始化工作,使用析构方法完成一些对象在销毁之前的清理工作

1.构造方法

在每个声明的类中都有一个呗称为构造方法的特殊成员方法,如果没有显式的声明它,类中都会默认存在一个没有参数列表并且内容为空的构造方法。如果显式的声明它,则类中的默认构造方法将不会存在。当创建一个对象时,构造方法就会被自动调用一次,即每次使用关键词new来实例化对象时都会自动调用构造方法,不能主动通过对象的引用调用构造方法。所以通常使用构造方法来执行一些有用的初始化任务,比如对成员属性在创建对象时赋初值等。

在PHP5以前的版本中,构造方法的方法名称必须与类名相同,这种方式在PHP 5中任然可以使用。但在PHP中很少声明和类名同名的构造方法了,这样做的好处是可以使构造函数独立于类名,当类名发生变化时不需要更改相应的构造函数名称。为了向下兼容,在创建对象时,如果一个类中没有名为__construct()的构造方法,PHP将搜索与类名相同名的构造方法执行。在类中声明构造方法的格式如下:

function __construct( [参数列表] ){ //构造方法名称是以两个下划线开始的
  //方法体,通常用来对成员属性进行初始化赋值
}

在PHP中,同一个类中只能声明一个构造方法。原因是构造方法名称是固定的,在PHP中不能声明同名的两个函数,所以也就没有构造方法重载。但可以在声明构造方法时使用默认参数,实现其他面向对象的编程语言中构造方法重载的功能。这样在创建对象时,如果在构造方法中没有传入参数,则使用默认参数为成员属性进行初始化。

  • 构造函数可以接受参数,能够在创建对象时赋值给对象属性
  • 构造函数可以调用类方法或其他函数
  • 构造函数可以调用其他类的构造函数

构造函数使用例子:

<?php
class Person{
  private $name;
  private $age;
  private $gender;
  public function __construct($name,$age,$gender){
    $this->setName($name);  //调用类方法
    $this->age = $age;
    $this->setGender($gender);
  }
  public function setName($name){
    $this->name = $name;
  }
  // ... setter 方法
}
$person = new Person("yeoman",23,'男');
?>

调用父类构造函数、调用无关类的构造函数:

function __construct(){
  parent::__construct(); // 调用父类的构造函数必须显示的使用parent调用父类构造函数
  classname::__construct(); // 调用其他类的构造函数,classname是类名
  //其他操作
}

继承和构造函数

PHP中的子类的构造函数不会主动调用父类的构造函数,要显示的使用parent::__construct()调用:

<?php
class Animal{
  private $name;
  function __construct($name){
    $this->setName($name)
    echo "动物类被创建!";
  }
  // ... 其他方法
}
class Birds extends Animal{
  private $name;
  private $leg;
  function __construct($name,$leg){
    parent::__construct($name); // 显示调用
    $this->setLeg($leg);
    echo "鸟类被创建!";
  }
  // ... 其他方法
}
?>

如果涉及多层继承,当调用parent::__construct()时,会沿着父类向上搜索,直到找到最合适的构造函数,例如:

// 接上例
class Parrot extends Birds{
  private $name;
  private $leg;
  private $wing;
  function __construct($name){
    parent::__construct($name); // 此时没有找到父类(Birds类)合适的构造函数,只能向上搜索,搜索到Animal类时,才找到合适的构造函数
    echo "鹦鹉类被创建!";
    $this->smackTalk();
    /*
    输出结果:
    "动物类被创建!"
    "鹦鹉说话!"
    */
  }
  function smackTalk(){
    echo "鹦鹉说话!";
  }
}

如果想要依次调用几个父类的构造函数,可以使用类名直接调用构造函数,例如:

function __construct($name,$leg){
    Animal::__construct($name); // 调用Animal构造函数
    Birds::__construct($name,$leg); // 调用Birds构造函数
}

2.析构函数

析构方法允许在销毁一个对象之前执行一些特定的操作,例如关闭文件,释放结果集等。

当堆内存段中的对象失去访问它的引用时,它就不能被访问了,也就成为垃圾对象了。通常对象的引用被赋予其他的值或者是在页面运行结束时,对象都会失去引用。

析构函数是在销毁对象时,自动调用的,不能显式的调用。析构函数不能带参数。

析构方法的声明格式如下:

function __deconstruct(){
  //方法体,通常用来完成一些在对象销毁前的清理任务
}

在以下几种情况下可能会调用析构函数(但不一定):

  • PHP页面加载完毕之后;
  • unset()类;
  • 变量引用指向别的对象或值时;
  • PHP的内存回收机制和JAVA的很类似,对没有任何引用的对象进行销毁回收,采用引用计数器的技术。

例子:

<?php
class test{
  function __destruct(){
    echo "当对象销毁时会调用!!!";
  }
}
$a = $b = $c = new test();
$a = null;
unset($b);
echo "<hr />";
?>

此例子,如下图,有三个变量引用$a,$b,$c指向test对象,test对象就有3个引用计数,当$a = null时,$a对test对象的引用丢失,计数-1,变为2,当$b被unset()时,$b对test对象的引用也丢失了,计数再-1,变为1,最后页面加载完毕,$c指向test对象的引用自动被释放,此时计数再-1,变为0,test对象已没有变量引用,就会被销毁,此时就会调用析构函数。

PHP面向对象程序设计之构造方法和析构方法详解

在PHP中析构方法并不是很常用,它属于类中可选的一部分,只有需要时才在类中声明。

<?php
class Person{
  var $name;
  var $sex;
  var $age;
  function __construct($name, $sex, $age){
    $this->name = $name;
    $this->sex = $sex;
    $this->age = $age;
  }
  function __destruct(){
    echo "再见" . $this->name . "<br />";
  }
}
$person1 = new Person("张三三", "男", 23);
$person1 = null;  //第一个对象将失去引用
$person2 = new Person("李四四", "女", 17);
$person3 = new Person("王五五", "男", 43);
?>

运行结果:

再见张三三
再见王五五
再见李四四

第一个对象在声明完成以后,它的引用就被赋予了空值,所以第一个对象最先失去的引用,不能再被访问了,人后自动调用第一个对象中的析构方法输出“再见张三三”。后面声明的两个对象都是在页面执行结束时失去的引用,也都自动调用了析构方法。但因为对象的引用都是放在栈内存中的,由于栈的后进先出特点,最后创建的对象会被最先释放,多以先自动调用第三个对象的析构方法,最后才调用第二个对象的析构方法。

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
PHP数据缓存技术
Feb 14 PHP
PHP在特殊字符前加斜杠的实现代码
Jul 17 PHP
phpmyadmin3 安装配置图解教程
Mar 29 PHP
PHP序列号生成函数和字符串替换函数代码
Jun 07 PHP
PHP下打开phpMyAdmin出现403错误的问题解决方法
May 23 PHP
php支付宝接口用法分析
Jan 04 PHP
详解php设置session(过期、失效、有效期)
Nov 12 PHP
浅谈PHP拦截器之__set()与__get()的理解与使用方法
Oct 18 PHP
laravel 5.1下php artisan migrate的使用注意事项总结
Jun 07 PHP
PHP设计模式之抽象工厂模式实例分析
Mar 25 PHP
TP5框架实现的数据库备份功能示例
Apr 05 PHP
php生成短网址/短链接原理和用法实例分析
May 29 PHP
PHP Cli 模式设置进程名称的方法
Jun 12 #PHP
PHP面向对象程序设计之对象克隆clone和魔术方法__clone()用法分析
Jun 12 #PHP
PHP面向对象程序设计之对象的遍历操作示例
Jun 12 #PHP
PHP面向对象程序设计内置标准类,普通数据类型转为对象类型示例
Jun 12 #PHP
PHP下用Swoole实现Actor并发模型的方法
Jun 12 #PHP
PHP面向对象类型约束用法分析
Jun 12 #PHP
PHP面向对象程序设计__tostring()和__invoke()用法分析
Jun 12 #PHP
You might like
推荐php模板技术[转]
2007/01/04 PHP
PHP写入WRITE编码为UTF8的文件的实现代码
2008/07/07 PHP
关于php连接mssql:pdo odbc sql server
2011/07/20 PHP
php查询mysql数据库并将结果保存到数组的方法
2015/03/18 PHP
CI分页类首页、尾页不显示的解决方法
2016/03/28 PHP
php文件上传及下载附带显示文件及目录功能
2017/04/27 PHP
如何用javascript去掉字符串里的所有空格
2007/02/08 Javascript
js switch case default 的用法示例介绍
2013/10/23 Javascript
nodejs批量修改文件编码格式
2015/01/22 NodeJs
在JavaScript中使用对数Math.log()方法的教程
2015/06/15 Javascript
Bootstrap Modal遮罩弹出层(完整版)
2016/11/21 Javascript
使用AngularJS对表单提交内容进行验证的操作方法
2017/07/12 Javascript
jquery+css实现下拉列表功能
2017/09/03 jQuery
vue-cli3.0配置及使用注意事项详解
2018/09/05 Javascript
this在vue和小程序中的使用详解
2019/01/28 Javascript
详解vue在项目中使用百度地图
2019/03/26 Javascript
Vue 组件修改根实例的数据的方法
2019/04/02 Javascript
判断“命令按钮”是否被鼠标单击详解
2019/07/31 Javascript
nodejs实现百度舆情接口应用示例
2020/02/07 NodeJs
vue监听dom大小改变案例
2020/07/29 Javascript
JavaScript判断数据类型有几种方法及区别介绍
2020/09/02 Javascript
[01:55]2014DOTA2国际邀请赛快报:国土生病 紧急去医院治疗
2014/07/10 DOTA
Python获取基金网站网页内容、使用BeautifulSoup库分析html操作示例
2019/06/04 Python
python-tkinter之按钮的使用,开关方法
2019/06/11 Python
使用 Python 处理 JSON 格式的数据
2019/07/22 Python
python多线程同步之文件读写控制
2021/02/25 Python
Spark处理数据排序问题如何避免OOM
2020/05/21 Python
python是怎么被发明的
2020/06/15 Python
python+selenium爬取微博热搜存入Mysql的实现方法
2021/01/27 Python
洲际酒店集团英国官网:IHG英国
2019/07/10 全球购物
2014年上半年工作自我评价
2014/01/18 职场文书
本科生自荐信
2014/06/18 职场文书
“六查”、“三学”、“三干”查摆问题整改措施
2014/09/27 职场文书
个人作风建设自查报告
2014/10/22 职场文书
2019入党申请书范文3篇
2019/08/21 职场文书
pytorch损失反向传播后梯度为none的问题
2021/05/12 Python