构造方法的定义
构造方法又称为构造函数、是对象被创建时自动调用的方法、用来完成类初始化的工作。
特性
- 构造方法和其他函数一样、可以传递参数、可以设定参数默认值。
- 构造方法可以调用属性、也可以调用方法。
- 构造方法可以被其他方法显式调用。
构造方法的声明
在PHP5中规定构造方法使用 __construct()函数表示构造方法,
在PHP4中使用与类名同名的方法为构造方法。在PHP5中依然支持了这种方式。PHP7.09报错但也输出了结果
<?php
class Test
{
public $name = "李四";
public $age = 23;
public function __construct()
{
echo "我是构造方法";
}
}
$p = new Test();
//既然是构造方法对象初始化自动调用的,那么下个例子
echo "<br/>;";
class Test2
{
public $name;
public $age;
public function __construct($name, $age = null)
{
echo $this->name = $name, "的年龄是" . $this->age = $age;
}
public function setNameAge($name)
{
//通过方法内部调用构造函数
$this->__construct($name);
}
}
$name = "李四";
$age = "24";
$p2 = new Test2($name, $age); //直接输出 李四的年龄是24
echo "<br/>";
//直接调用构造函数
$p2->__construct("张三", 12); //echo 的年龄 xxx
echo "<br/>";
$p2->setNameAge("赵四");
析构函数和垃圾回收机制
析构函数:当某个对象的所有引用都被删除(成为垃圾)或者当对象被显式销毁时执行的函数,也就是对象在内存中被销毁前调用析构函数。
特性
析构函数是PHP新增的、析构函数是由系统自动调用的,虽然析构函数也可以被现实调用,但强烈建议不要使用。声明析构函数名称必须是__destruct(),并且不能带有参数。
PHP的垃圾回收机制
在PHP中,没有任何变量指向这个对象时,这个对象就成为垃圾。PHP会将其在内存中销毁。这是PHP的GC(Garage Collector)垃圾处理机制,目的是防止内存溢出。
PHP中变量在内存中是存在于一个ZVAL的变量容器中。结构如下
变量类型 变量值 is_ref
refcount
is_ref
是个bool值,用来区分变量是否属于引用集合。表示变量是否有一个以上的别名。
refcount
引用计数器,表示指向这zval变量容器的变量个数。当refcount值为1时,is_ref的值false。因为refcount为1,此变量不可能有多个别名,也就不存在引用了。为refcount为0时,zval以成为垃圾可回收。
<?php
class Test{
public function __construct()
{
echo "有新对象创建了<br/>";
}
public function __destruct()
{
echo "有对象销毁了<br/>";
}
}
//当运行脚本结束之后调用析构函数
$p=new Test();
echo "<hr/>"; 运行结果是横线下方: 有对象销毁了
显示的销毁对象、调用析构
<?php
class Test
{
public function __construct()
{
echo "有新对象创建了<br/>";
}
public function __destruct()
{
echo "有对象销毁了<br/>";
}
}
//当运行脚本结束之后调用析构函数
$p = new Test();
//此函数是PHP调试函数 必须需要装扩展xdebug、用来查看引用的
echo xdebug_debug_zval('p');
unset($p);
//显示的销毁对象、自动调用析构
$p = 2;
//$p重新赋值、等对象没有了引用、变成垃圾自动销毁
echo xdebug_debug_zval('p');
echo "<hr/>";
//我是横线 在最下方
当refcount值为0的时候,会自动调用__destruct.会执行PHP的垃圾回收机制。
<?php
class Test{
public function __construct()
{
echo "有新对象创建了<br/>";
}
public function __destruct()
{
echo "有对象销毁了<br/>";
}
}
//当运行脚本结束之后调用析构函数
$p=new Test();
echo xdebug_debug_zval('p');
$p1=$p; //$p1指向 test类
echo xdebug_debug_zval('p');
unset($p); //会不会调用__destruct()? 答案是不会。虽然删除了$p但是 但是$p1还是在引用test
echo xdebug_debug_zval('p1');
echo "<hr/>"; // 有对象销毁了。在横线的上面。 除非在unset($p1)会在横线上面re
refcount通过赋值就能增加 is_ref通过引用赋值增加
<?php
class Test
{
public function __construct()
{
echo "有新对象创建了<br/>";
}
public function __destruct()
{
echo "有对象销毁了<br/>";
}
}
//当运行脚本结束之后调用析构函数
//$p=$p1=$p2=new Test();
//echo xdebug_debug_zval('p');
//增加了refcount的值 、对象实际存放一个
//通过引用赋值 增加is_ref 引用地址赋值
$p[] = new Test();
$p[] =&$p;
echo xdebug_debug_zval('p');
unset($p); //删除 $p对象 但并没销毁、$p内部还有一个指向
echo "<br/>";