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&amp;mysql(二)
Oct 09 PHP
PHP session会话的安全性分析
Sep 08 PHP
php错误、异常处理机制(补充)
May 07 PHP
php实现的一个很好用HTML解析器类可用于采集数据
Sep 23 PHP
PHP生成随机密码方法汇总
Aug 27 PHP
php根据日期或时间戳获取星座信息和生肖等信息
Oct 20 PHP
PHP使用strstr()函数获取指定字符串后所有字符的方法
Jan 07 PHP
PHP获取用户访问IP地址的5种方法
May 16 PHP
ThinkPHP 模板引擎使用详解
May 07 PHP
Mac系统完美安装PHP7详细教程
Jun 06 PHP
PHP实现的超长文本分页显示功能示例
Jun 04 PHP
PDO::quote讲解
Jan 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
Zend Studio去除编辑器的语法警告设置方法
2012/10/24 PHP
ThinkPHP自定义函数解决模板标签加减运算的方法
2015/07/03 PHP
Ubuntu彻底删除PHP7.0的方法
2018/07/27 PHP
javascript 限制输入脚本大全
2009/11/03 Javascript
NodeJS 模块开发及发布详解分享
2012/03/07 NodeJs
JS实现鼠标点击展开或隐藏表格行的方法
2015/03/03 Javascript
分享网页检测摇一摇实例代码
2016/01/14 Javascript
两种方法解决javascript url post 特殊字符转义 + &amp; #
2016/04/13 Javascript
JS原型链 详解及示例代码
2016/09/06 Javascript
Boostrap基础教程之JavaScript插件篇
2016/09/08 Javascript
用nodejs搭建websocket服务器
2017/01/23 NodeJs
简单的jQuery拖拽排序效果的实现(增强动态)
2017/02/09 Javascript
Vue实现购物车功能
2017/04/27 Javascript
微信小程序利用Canvas绘制图片和竖排文字详解
2019/06/25 Javascript
Node 代理访问的实现
2019/09/19 Javascript
nodejs各种姿势断点调试的方法
2020/06/18 NodeJs
Python基于动态规划算法解决01背包问题实例
2017/12/06 Python
Python实现扣除个人税后的工资计算器示例
2018/03/26 Python
python3获取两个日期之间所有日期,以及比较大小的实例
2018/04/08 Python
解决django前后端分离csrf验证的问题
2019/02/03 Python
查看python安装路径及pip安装的包列表及路径
2019/04/03 Python
详解Python下载图片并保存本地的两种方式
2019/05/15 Python
利用pyuic5将ui文件转换为py文件的方法
2019/06/19 Python
python打造爬虫代理池过程解析
2019/08/15 Python
python 和c++实现旋转矩阵到欧拉角的变换方式
2019/12/04 Python
Python importlib动态导入模块实现代码
2020/04/16 Python
美国玩具公司:U.S.Toy
2018/05/19 全球购物
Keds加拿大官网:购买帆布运动鞋和皮鞋
2019/09/26 全球购物
英国豪华家具和家居用品购物网站:Teddy Beau
2020/10/12 全球购物
演讲比赛获奖感言
2014/02/02 职场文书
竞选班长的演讲稿
2014/04/24 职场文书
机房搬迁方案
2014/05/01 职场文书
公司承诺书格式
2014/05/21 职场文书
社保代办委托书怎么写
2014/10/06 职场文书
委托公证书格式
2015/01/26 职场文书
Python 流媒体播放器的实现(基于VLC)
2021/04/28 Python