序列化,异常类以及匿名类
1.演示 sleep()
,wakeup()
__sleep()
- 触发事件:对象被序列化之前
- 作用:返回需要被序列化存储的成员属性,删减不必要
__sleep()
不能返回父类的私有成员的名字。这样做会产生一个 E_NOTICE 级别的错误。可以用 Serializable 接口来替代。 __wakeup()
- 触发事件:类的实例的序列化串被反序列化时
- 作用:预先准备对象资源,重新创建新的对象
<?php
class Nicola
{
private $name;
private $age;
private $sex;
private $info;
//构造函数
public function __construct($name, $age, $sex)
{
$this->name = $name;
$this->age = $age;
$this->sex = $sex;
$this->info = sprintf(
"基本信息,昵称: %s age: %d sex: %s",
$this->name,
$this->age,
$this->sex
);
}
public function getInfo()
{
echo $this->info;
}
/**
* serialize前调用 用于删选需要被序列化存储的成员变量
* @return array [description]
*/
public function __sleep()
{
echo __METHOD__ . '<br>';
//序列化时只会存储 name age sex, info 不会被序列化
return ['name', 'age', 'sex'];
}
/**
* unserialize前调用 用于预先准备对象资源
*/
public function __wakeup()
{
echo __METHOD__ . '<br>';
$this->info = sprintf(
"基本信息, 昵称: %s age: %d sex: %s",
$this->name = '尼古拉',
$this->age = '18',
$this->sex = '保密'
);
}
}
$nicola = new Nicola('朱老师', 40, '男');
//构造函数组装的 $info
$nicola->getInfo();
//序列化时并不会存储 $info 属性
echo '<hr>';
$temp = serialize($nicola);
echo $temp;
echo '<hr>';
//反序列化时会调用 __wakeup() 函数
$nicola = unserialize($temp);
//__wakeup() 组装的 $info
$nicola->getInfo();
2. 自定义异常类
- 自定义的异常类必须是系统异常类的子类
- 当系统异常类的功能和需求不能满足的时候就需要定义自己的异常处理类
2.1 系统的异常类
<?php
class Exception {
protected $message; // 异常信息
protected $code; // 用户自定义异常代码
protected $file; // 发生异常的文件名
protected $line; // 发生异常的代码行号
final private function __clone() { }
public function __construct($message = "", $code = 0, Throwable $previous = null) { }
final public function getMessage() { } //返回异常信息
final public function getCode() { } // 返回异常代码
final public function getFile() { } // 返回发生异常的文件名
final public function getLine() { } // 返回发生异常的代码行号
final public function getTrace() { } // backtrace() 数组
final public function getPrevious() { } // 返回异常链中的前一个异常
final public function getTraceAsString() { } // 已格成化成字符串的 getTrace() 信息
/* 可重载的方法 */
public function __toString() { } // 可输出的字符串
2.2 自定义异常类演示
<?php
//我们知道系统有预定义的父类Exception
//因此,自定义的必须是这个预定义的子类
class MyException extends Exception
{
//重定义构造器使第一个参数 message code变为必须被指定的属性
public function __construct($message, $code)
{
//parent::construct()来检查所有的变量是否已被赋值
parent::__construct($message, $code);
}
//使用魔术方法,把实例对象输出为字符串
//重写父类方法,自定义字符串输出的样式
public function __toString()
{
//HERDOC的后面不能有空格
return <<< "NICOLA"
<table>
<tr>
<th>代码</th>
<th>内容</th>
<th>脚本</th>
<th>行</th>
</tr>
<tr>
<td>{$this->getCode()}</td>
<td>{$this->getMessage()}</td>
<td>{$this->getFile()}</td>
<td>{$this->getLine()}</td>
</tr>
</table>
NICOLA;
}
}
3. 写一个匿名类小案例演示
- PHP 从 7 开始支持匿名类,通常匿名类用来创建一次性的简单对象,匿名类可以继承其他类、实现接口、使用 trait,还可以向其构造函数传递参数。
<?php
//匿名类
// 直接定义
$objA = new class
{
public function getName()
{
echo "I'm objA";
}
};
$objA->getName();
// 方法中返回
function testA()
{
return new class
{
public function getName()
{
echo "I'm testA's obj";
}
};
}
$objB = testA();
$objB->getName();
// 作为参数
function testB($testBobj)
{
echo $testBobj->getName();
}
testB(new class
{
public function getName()
{
echo "I'm testB's obj";
}
});
4. 总结
本节课最大的亮点就是匿名类的使用,可惜只能用于 7.0+以后的版本,通过 new class 来实例化一个匿名类,这可以用来替代一些”用后即焚”的完整类定义