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分页示例分享
Apr 30 PHP
Smarty模板学习笔记之Smarty简介
May 20 PHP
php 伪静态之IIS篇
Jun 02 PHP
php 利用socket发送HTTP请求(GET,POST)
Aug 24 PHP
非常重要的php正则表达式详解
Jan 04 PHP
php采集神器cURL使用方法详解
Feb 19 PHP
PHP针对多用户实现更换头像功能
Sep 04 PHP
利用PHP绘图函数实现简单验证码功能的方法
Oct 18 PHP
PHP处理Ajax请求与Ajax跨域问题
Feb 13 PHP
php nginx 实时输出的简单实现方法
Jan 21 PHP
php实现生成带二维码图片并强制下载功能
Feb 24 PHP
基于PHP+mysql实现新闻发布系统的开发
Aug 06 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
php5.3 注意事项说明
2013/07/01 PHP
ThinkPHP使用UTFWry地址库进行IP定位实例
2014/04/01 PHP
php实现的微信红包算法分析(非官方)
2015/09/25 PHP
PHP简单日历实现方法
2016/07/20 PHP
php制作基于xml的RSS订阅源功能示例
2017/02/08 PHP
PHP实现活动人选抽奖功能
2017/04/19 PHP
Laravel 解决composer相关操作提示php相关异常的问题
2019/10/23 PHP
PHP连接MySQL数据库的三种方式实例分析【mysql、mysqli、pdo】
2019/11/04 PHP
学习YUI.Ext 第六天--关于树TreePanel(Part 1)
2007/03/10 Javascript
window.requestAnimationFrame是什么意思,怎么用
2013/01/13 Javascript
JavaScript去除空格的三种方法(正则/传参函数/trim)
2013/02/06 Javascript
使用javascript实现页面定时跳转总结篇
2013/09/21 Javascript
Js 去掉字符串中的空格(实现代码)
2013/11/19 Javascript
JS获取各种浏览器窗口大小的方法
2014/01/14 Javascript
从零学jquery之如何使用回调函数
2014/05/16 Javascript
jQuery验证插件validate使用详解
2016/05/11 Javascript
纯js实现隔行变色效果
2017/11/29 Javascript
JS与CSS3实现图片响应鼠标移动放大效果示例
2018/05/04 Javascript
如何利用Node.js与JSON搭建简单的动态服务器
2020/06/16 Javascript
vue-iview动态新增和删除的方法
2020/06/17 Javascript
在Debian下配置Python+Django+Nginx+uWSGI+MySQL的教程
2015/04/25 Python
JPype实现在python中调用JAVA的实例
2017/07/19 Python
Python list与NumPy array 区分详解
2019/11/06 Python
使用Python生成200个激活码的实现方法
2019/11/22 Python
如何基于python实现脚本加密
2019/12/28 Python
Python Selenium模块安装使用教程详解
2020/07/09 Python
python如何支持并发方法详解
2020/07/25 Python
HTML5 canvas实现移动端上传头像拖拽裁剪效果
2016/03/14 HTML / CSS
银行门卫岗位职责
2013/12/29 职场文书
给儿子的表扬信
2014/01/15 职场文书
2014年教研组工作总结
2014/11/26 职场文书
2014年挂职干部工作总结
2014/12/06 职场文书
房租涨价通知
2015/04/23 职场文书
2016党员入党决心书
2015/09/22 职场文书
Windows11插耳机没反应怎么办? win11耳机没声音的多种解决办法
2021/11/21 数码科技
SQL Server表分区降低运维和维护成本
2022/04/08 SQL Server