PHP-OOP-Learning-Notes
面向对象介绍
介绍
面向对象是一个编程思想,编程思想有面向过程和面向对象
面向对象:编程思路集中的是在过程中
面向对象:编程思路集中在参与的对象
以去饭馆吃饭为例子:
面向过程:点菜—————上菜————吃饭————结账————收拾
面向对象:服务员、厨师、客人
面向对象的好处
- 多人合作方便
- 减少代码冗余、灵活性高
- 代码的可重复用性发挥到了极致
- 可扩展性强
多学一招:
OOP: Object-Oriented Program
OOA: Object-Oriented Analysis
OOD: Object-Oriented Designed
类和对象
- 对象是具体存在的事物,对象是由
属性(变量)和 方法(函数)
组成的 - 类是具有
相同属性和行为的一组对象的集合
(有相同变量和函数的一组集合 对象只是集合中的一个元素)
分析: 做菜动作——厨师对象——厨师类
结论: 我们在开发的时候---->先写类---->通过类创建对象---->然后调用对象的属性和方法实现功能
类——对象——调用成员
注意:一个类可以创建多个对象
小结
- 对象是由属性和方法组成的
- 类是所有对象的相同属性和方法的集合
- 在开发的时候 先写类 通过类创建对象 然后调用对象的属性和方法实现功能
- 一个类可以创建多个对象
在PHP中实现类和对象
创建类
class 类名{
// 属性
// 方法
// 常量
}
# 类成员有 属性 方法 常量
类名的命名规则:
- 以字母、下划线开头(不能用数字开头)
- 不能用PHP关键字
- 类名不区分大小写 (变量名区分 关键字 类名不区分大小写)
- 类名用帕斯卡命名法 (大驼峰 单词的首字母大写)(非必须)
<?php
class Student{
}
?>
对象实例化
通过new关键字
来实例化对象
<?php
# 定义类
class Student{
}
# 实例化对象
$stu1 = new Student(); //括号写不写都行
$stu2 = new Student; //偷懒写法
var_dump($stu1,$stu2);
#输出结果
#object(Student)#1 (0) {}
#object(Student)#2 (0) {}
// 这里注意虽然都是$stu1、$stu2 对象的实例化 但是他们的编号不一样 有先后顺序
对象比较
注意:对象的之间的赋值、或叫做对象之间的传递是地址的传递(简单来说 就是共用一份内存)
相等:结构和保存的值一样就相等
全等:指向同一个对象才是全等
<?php
# 定义类
class Student{
}
# 实例化对象
$stu1 = new Student();
$stu2 = new Student;
$stu3 = $stu2; // 对象传递默认的是地址 就是共享内存 就像一家人一样
//var_dump($stu1,$stu2,$stu3);
// object(Student)#1 (0) {} object(Student)#2 (0) {} object(Student)#2 (0) {}
var_dump($stu2===$stu3); // bool(true) 编号相同是同一个对象
var_dump($stu1==$stu2); // bool(true) 比较对象的结构
var_dump($stu1===$stu2); // bool(false) 比较对象是否是同一个 编号不相同 只是双胞胎但不是同一个人
?>
属性
属性的本质就是变量
通过->调用
对象的成员或对象名->属性名
对象名->方法名字
<?php
// 定义类
class Student{
public $name;
public $add = '地址不详';
}
// 实例化对象
$stu = new student(); //把这个对象赋值给$stu变量
print_r($stu);
/* Student Object
(
[name] =>
[add] => 地址不详
) */
// 给属性赋值
$stu->name = 'tom';
$stu->add = '北京';
// 获取属性的值
echo '姓名:'.$stu->name."\n";
echo '地址:'.$stu->add."\n";
/* 姓名:tom
地址:北京 */
// 添加一个属性 只要添加了就是公有的
$stu->age = 20;
print_r($stu);
/*
Student Object
(
[name] => tom
[add] => 北京
[age] => 20
)*/
// 删除属性
unset($stu->add);
print_r($stu);
/* Student Object
(
[name] => tom
[age] => 20
)*/
总结:
- 对公有属性的赋值:$stu->name = 'tom'; $stu->add = '北京';
- 添加公有属性:$stu->age = 20;
- 删除公有的属性:unset($stu->add);
<?php
class Student{
public $name;
}
$stu1 = new Student;
$stu2 = new Student;
$stu1->name='tom';
var_dump($stu1==$stu2); //bool(false)
这里为啥bool值是0呢?虽然结构相同 == 指的是相等
- 结构相同
- 值相等
明显结构相同 但是值发生了变化
方法
方法的本质就是函数
<?php
class Student{
// 定义方法 public对于方法可以省略
public function show(){
echo "这是一个show方法"."\r\n";
}
function test(){
echo "test方法";
}
}
// 新建一个对象
$stu = new Student;
// 用对象调用方法 也就是这个函数
$stu->show();
$stu->test();
/* 这是一个show方法
test方法 */
tips: public对于方法可以省略 属性前面的public不能省略
访问修饰符
用来控制成员的访问权限
修饰符 | 描述 |
---|---|
public | 在类的内部和外部都能访问 |
private | 只能在内部访问 |
protected(受保护的) | 在整个继承链上访问 |
tips:一般来说 属性都是私有的 通过公有的方法对私有的属性进行赋值和取值
==作用:保证数据的合法性== 感觉就是出于安全性的考虑
<?php
class Student{
private $name; //私有属性
private $sex; //私有属性
// 通过公有方法对私有属性进行赋值
public function setinfo($name,$sex){
if ($sex!='man' && $sex!='woman') {
echo '性别必须是男或女';
exit;
}
$this->name=$name; //this 表示当前对象
$this->sex=$sex;
}
/* 上面的setinfo()函数定义了一个公有方法 对姓名和性别的赋值
但是对性别进行了限制 用if来判断传进来的值
在判断之后对实例化的 当前对象的属性进行了赋值
$this->属性 = $变量
*/
// 定义函数进行输出
public function getinfo(){
echo 'name:'. $this->name."\n";
echo 'sex:'. $this->sex."\n";
}
}
$stu = new Student;
$stu->setinfo("tom",'man');
$stu->getinfo(); //name:tom sex:man
$stu2 = new Student;
$stu->setinfo("berry",'woman');
$stu->getinfo(); //name:berry sex:woman
我们可以实验一下 传入非法参数会怎么样?
$stu3 = new Student;
$stu3->setinfo("hacker", 'hacker');
$stu3->getinfo(); //性别必须是男或女
类和对象在内存中的分布
- 对象的本质是一个
复杂的变量
- 类的本质是一个自定义的
复杂数据类型
- 栈区:运行速度快 体积小 保存基本类型
- 堆区:运行速度稍慢 体积大 保存复杂类型
- 实例化的过程就是分配内存空间的过程
- 对象保存在堆区 将堆区的地址保存在栈区
封装
有选择性的提供数据
通过访问修饰符来实现封装
构造方法
介绍
构造方法也叫构造函数,当实例化一个对象的时候自动执行
function __construct(){
}
// 注意前面是两个下划线
例题
<?php
class Student{
// 和类名同名的方法是构造方法 在php中不建议这种写法
public function __construct(){
echo "这是构造方法"."\n";
}
}
new Student;
new Student;
/* 这是构造方法
这是构造方法 */
构造方法的作用:初始化成员变量
析构方法
介绍
当对象销毁的时候自动调用
function __destruct{
}
tips:析构函数不可以带参数
例题
<?php
class Student{
private $name; //私有属性
private $sex; //私有属性
// 公有的构造方法对私有属性赋值
public function __construct($name){
$this->name=$name;
echo "{$this->name} is born \n";
}
// 析构方法
public function __destruct(){
echo "{$this->name} has died \n";
}
}
$stu = new Student('tom'); //实例化对象的时候传入参数
$stu1 = new Student('berry');
$stu2 = new Student('jack');
输出结果:
tom is born
berry is born
jack is born
jack has died
berry has died
tom has died
计算机的内存管理
计算机内存的管理方式有:先进先出,先进后出
先进先出的内存管理方式一般用在业务逻辑中,比如秒杀、购票
等等
管道里面排队的例子
----》在一个管道里面 先进来的人先出去
先进后出是计算机的默认内存管理方式
茶杯排队的例子
-----》在一个茶杯里面 先进来的人被压在最底下 动弹不得 得前面的人走光了才能出去
思考题1
<?php
class Student{
private $name; //私有属性
private $sex; //私有属性
// 公有的构造方法对私有属性赋值
public function __construct($name){
$this->name=$name;
echo "{$name} is born \n";
}
// 析构方法
public function __destruct(){
echo "{$this->name} has died \n";
}
}
$stu = new Student('tom');
$stu1 = new Student('berry');
$stu2 = new Student('jack');
unset($stu1);
输出结果:
tom is born
berry is born
jack is born
berry has died
jack has died
tom has died
分析:
- 实例化了三个对象 依次是tom berry jack
- 按照茶杯排队的原则 最先实例化的对象是tom最后一个死亡
- 又因为手动销毁了berry 所以死亡顺序是 berry jack tom
思考题2
<?php
class Student{
private $name; //私有属性
private $sex; //私有属性
// 构造方法
public function __construct($name){
$this->name=$name;
echo "{$name} is born \n";
}
// 析构方法
public function __destruct(){
echo "{$this->name} has died \n";
}
}
new Student('tom');
new Student('berry');
new Student('jack');
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
tom is born
tom has died
berry is born
berry has died
jack is born
jack has died
分析:
- 因为实例化对象没有赋值给变量?在内存中实例化就销毁了 好旧之前学的忘记了
- 一实例化马上就死掉了
思考题3
<?php
class Student{
private $name; //私有属性
private $sex; //私有属性
// 构造方法
public function __construct($name){
$this->name=$name;
echo "{$name} is born \n";
}
// 析构方法
public function __destruct(){
echo "{$this->name} has died \n";
}
}
$stu = new Student('tom');
$stu = new Student('berry');
$stu = new Student('jack');
----------------------------------------------------------------------------------------------------------
tom is born
berry is born
tom has died
jack is born
berry has died
jack has died
分析:
- 实例化tom 然后实例化berry
- tom被销毁 然后实例化jack
- berry被销毁 最后销毁jack
继承
继承介绍
- 继承使得代码具有层次结构
- 子类继承了父类的属性和方法,实现了代码的可重用性(实际感觉就是一个类一个文件 这样方便找错 结构也更清楚)
- 使用extends关键字实现继承
- 父类和子类是相对的
语法:
<?php
// 定义一个父类
class Person{
public function show(){
echo "这是一个人类";
}
}
// 定义一个子类继承父类
class Student extends Person{
}
$stu = new student;
$stu->show(); //子类继承父类的方法
//这是一个人类
执行过程:
第一步:在Student类中去找show() 如果找不到就调用 找不到就到父类中去查找
第二步:在Person类中查询show()
子类中调用父类成员
<?php
// 定义一个父类
class Person{
public function show(){
echo "这是一个人类";
}
}
// 定义一个子类继承父类
class Student extends Person{
public function test(){
// 方法一
/* $person = new Person();
$person->show(); */
// 方法二
$this->show();
}
}
$stu = new student;
$stu->test();
//这是一个人类
小结:
- 通过实例化父类调用父类的成员
- 通过$this关键字调用父类成员
Protected
protected:受保护的 在整个继承链上都能访问 也就是说在子类和父类中都能够使用
<?php
class Person{
public function getNum(){
echo $this->num;
}
}
class Student extends Person{
protected $num = 10;
}
$obj = new Student(); //整个继承链上有A和B
$obj -> getNum();
// 输出结果为10
tips:子类继承父类的非私有属性和非私有方法
<?php
class Person{
public function getNum(){
echo $this->num;
}
}
class Student extends Person{
protected $num = 10;
}
$obj = new Person(); // 整个继承链上只有A
$obj -> getNum();
// Notice: Undefined property: Person::$num
继承中的构造函数
规则:
1、如果子类有构造函数就调用子类的,如果子类没有就调用父类的构造函数
2、子类的构造函数调用后,默认就不再调用父类的构造函数
通过类名调用父类的构造函数
类名::__construct()
例题
<?php
class Persons{
public function __construct(){
echo "这是父类方法\n";
}
}
class Student extends Persons{
public function __construct(){
//Person::__construct(); // 调用父类的构造函数
parent::__construct(); // parent表示父类的名字
echo "这是子类方法\n";
}
}
new Student(); // 耦合性高 联系紧密
注意:parent关键字表示父类的名字 可以降低程序的耦合性 耦合性越低越好
例题:给父类传递参数
<?php
class Persons{
protected $name; //受保护的属性 在整个继承链上使用
protected $sex; //受保护的属性 在整个继承链上使用
// 父类的公有构造方法对父类的属性进行赋值
public function __construct($name,$sex){
$this->name = $name;
$this->sex = $sex;
}
}
class Student extends Persons{
private $score; //私有的属性 只能在类的内部使用
public function __construct($name,$sex,$score){
parent::__construct($name,$sex); //调用父类构造函数并传递参数
$this->score = $score;
}
public function getinfo(){
echo "name:{$this->name}\n";
echo "sex:{$this->sex}\n";
echo "score:{$this->score}\n";
}
}
$stu = new Student('tom','man',88); // 耦合性高 联系紧密
$stu -> getinfo();
/* name:tom
sex:man
score:88 */
$this详解
$this表示当前对象的地址,也就是$this保存的当前对象的地址
<?php
class A{
public function __construct(){
var_dump($this);
}
}
class B extends A{
}
new A(); //object(A)#1 (0) {}
new B(); //object(B)#1 (0) {}
多重继承
PHP不允许多重继承 因为多重继承容易产生二义性
A--->B--->C
多态
多态:多种形态
多态分为两种:方法重写和方法重载
方法重写
简单理解就是子类把父类的同名函数重新命名一遍
子类重写了父类的同名方法(函数名相同 形参相同)
<?php
class Person{
public function show(){
echo 'parent';
}
}
class Student extends Person{
public function show(){
echo 'son';
}
}
// 子类重写了父类的同名方法
$stu = new Student;
$stu -> show(); // 输出结果:son
注意事项:
- 子类的方法必须和父类的
方法名相同
- 参数个数要
一致
- 子类修饰的
不能比父类更加严格
方法重载
简单理解 就是同名函数用不同的参数来重新加载
在一个类中 有多个同名的函数 通过参数的个数不同来区分不同的方法 称为方法重载
<?php
class Student{
public function show(){
}
public function show($num){
}
public function show($num1,$num2){
}
}
注意:PHP不支持方法重载 但是可以通过其他方法来模拟方法重载
面向对象的三大特性
- 封装(通过访问修饰符去封装)
- 继承(通过extends去继承)
- 多态(多种形态)
私有属性继承重写
私有属性可以被继承但不可以重写
先来看看公有属性
<?php
class A{
public $name = 'PHP';
}
class B extends A{
// B类继承A类后面再重写掉$name
public $name = 'JAVA';
}
$obj = new B;
var_dump($obj); //object(B)#1 (1) {["name"]=>string(4) "JAVA"}
// echo $obj->name;
<?php
class A{
// 私有属性只能在类的内部访问 那是否能够被继承呢?
private $name = 'PHP';
}
class B extends A{
private $name = 'JAVA';
}
$obj = new B;
var_dump($obj);
// 说明私有属性也是可以被继承的 但是会有两个属性 一个是A类的 一个是B类的
/* object(B)#1 (2) {
["name":"B":private]=>
string(4) "JAVA"
["name":"A":private]=>
string(3) "PHP"
} */
<?php
class A{
private $name = 'PHP';
public function showa(){
var_dump($this);
// echo "$this->name\n";
}
}
class B extends A{
private $name = 'JAVA';
public function showb(){
var_dump($this);
// echo "$this->name\n";
}
}
$obj = new B;
$obj -> showa();
$obj -> showb();
输出结果:
object(B)#1 (2) {
["name":"B":private]=>
string(4) "JAVA"
["name":"A":private]=>
string(3) "PHP"
}
object(B)#1 (2) {
["name":"B":private]=>
string(4) "JAVA"
["name":"A":private]=>
string(3) "PHP"
}
<?php
class A{
private $name = 'PHP';
public function showa(){
// var_dump($this);
echo "$this->name\n";
}
}
class B extends A{
private $name = 'JAVA';
public function showb(){
//var_dump($this);
echo "$this->name\n";
}
}
$obj = new B;
$obj -> showa();
$obj -> showb();
PHP
JAVA
分析:
- $obj中有两个name 一个是公有的 一个是私有的 在showa()中既能访问私有的
- $name也能访问公有的$name 但是私有的比公有的权限高 所以输出的是tom 在showb()中只能访问公有的$name 所以输出berry
方法修饰符
方法修饰符有:static final abstract
Static 静态修饰符
- static修饰的属性叫静态属性、static修饰的方法叫静态方法
- 静态成员加载类的时候分配空间,程序执行完毕后销毁
- 静态成员在内存中就一份
- 调用语法 类名::属性 类名::方法名()
<?php
class Person{
public static $add = "北京\n";
public static function show(){
echo 'this is a static function';
}
}
echo Person::$add;
Person::show();
输出结果:
北京
this is a static function
统计在线人数:
<?php
class Student{
public static $num = 0;
function __construct(){
self::$num++;
}
function __destruct(){
self::$num--;
}
function new(){
echo '当前在线人数为:'.self::$num."\n";
}
}
$stu1 = new Student;
$stu2 = new Student;
$stu3 = new Student;
$stu2->new();
unset($stu2);
$stu3->new();
当前在线人数为:3
当前在线人数为:2
注意:self表示所在类的类名就是自己,使用self降低耦合性
静态延时绑定
static表示当前对象所属的类
<?php
class Person{
public static $add = 'China'."\n";
public static function show(){
echo 'this is people'."\n";
}
}
// 继承
class Student extends Person{
}
$stu = new Student;
echo Student::$add;
Student::show();
输出结果:
China
this is people
<?php
class Person{
public static $type = 'People'."\n";
public function show(){
echo static::$type."\n";
}
}
// 继承
class Student extends Person{
}
$obj = new Person;
$obj->show();
输出结果:
People
<?php
class Person{
public static $type = 'People'."\n";
public function show1(){
echo static::$type."\n";
}
}
// 继承
class Student extends Person{
public static $type = 'Student'."\n";
public function show2(){
echo static::$type."\n";
}
}
$obj = new Student;
$obj->show1();
$obj->show2();
输出结果:
Student
Student
分析:
可以看到student类继承了person类
static表示调用当前对象所属的类
所以输出的结果都是student
小结:
- static在内存中就一份,在类加载的时候就分配空间
- 如果有多个修饰符号、修饰符之间是没有顺序的
- self表示所在类的类名
- static表示调用当前对象所属的类 self表示当前类
- static有两个作用 第一表示静态的 第二表示类名
Final [最终的]
final修饰的方法不能被重写
final修饰的方法不能被继承
<?php
class Person{
// final修饰的方法不能被重写
public final function show(){
}
}
class Student extends Person{
public function show(){
}
}
/*Fatal error:
Cannot override final method Person::show()
in D:\phpStudy\PHPTutorial\WWW\f.com\PHP\Object\Final.php on line 11*/
<?php
final class Person{
// final修饰的方法不能被重写
public function show(){
}
}
class Student extends Person{
public function show(){
}
}
/* Fatal error: Class Student may not inherit from final class (Person) in
D:\phpStudy\PHPTutorial\WWW\f.com\PHP\Object\Final.php on line 12 */
作用
- 如果一个类确定不被继承,一个方法确定不会被重写,
用final修饰可以提高执行效率
- 如果一个方法不允许被其他类重写 可以用final修饰
abstract【抽象的】
- abstract 修饰的方法是抽象方法,修饰的类是抽象类
只有方法的声明没有方法的实现称为抽象方法
- 一个类中
只要有一个方法是抽象方法,这个类必须是抽象类
- 抽象类的特点是
不能实例化
- 如果
有子类继承了抽象类 那么必须将抽象方法重新实现 如果不重新实现 不允许实例化
- 类中没有
抽象方法也可以声明成抽象类,用来阻止类的实例化
例题
<?php
// 抽象类
abstract class Person{
//只有方法的声明没有方法的实现
public abstract function setinfo();
public function getinfo(){
echo "获取信息\n";
}
}
// 如果有类继承了抽象类 那么必须将抽象方法重新实现
// 如果不重新实现 不允许实例化
class Student extends Person{
// 重写实现父类的抽象方法
public function setinfo(){
echo "重新实现父类的抽象方法\n";
}
}
// 抽象类不允许被实例化
$person = new Person;
// Fatal error: Uncaught Error: Cannot instantiate abstract class Person
// 测试
$stu = new Student;
$stu->setinfo();
$stu->getinfo();
输出信息:
重新实现父类的抽象方法
获取信息
抽象类的作用
- 定义命名规范
- 阻止实例化,如果一个类中的所有方法都是静态方法,那么这时候没有必要去实例化,可以通过abstract来阻止实例化
类常量
类常量是const常量
<?php
class Student{
public const ADDR = "地址不详";
}
echo Student::ADDR;
//地址不详
问题:define常量和const常量的区别?
答:const常量可以做类成员,define常量不可以做类成员
问题:常量和静态属性的区别在哪里?
答:相同点:在加载类的时候分配空间
不同点:常量的值不可以更改
静态属性的值可以更改
接口(interface)
- 如果一个类中所有的方法都是抽象方法 那么这个抽象类就可以声明成接口
- 接口是一个特殊的抽象类
接口中只能有抽象方法和常量(function const)
- 接口中的抽象方法只能是public,可以省略,默认也是public的
- 通过implements关键字来实现接口
- 不能使用abstract和final来修饰接口中的抽象方法
<?php
// 用interface来声明接口
interface Student{
const ADDR = 'BJ';
function fun1();
function fun2();
}
// 接口实现
class Teacher implements Student{
public function fun1(){
}
public function fun2(){
}
}
echo Student::ADDR;
Implements 接口的多重实现
类不允许多重继承,但是接口允许多重实现
(举个例子 )
<?php
interface Ipic1{
function fun1();
}
interface Ipic2{
function fun2();
}
class Student implements Ipic1,Ipic2{
public function fun1(){
}
public function fun2(){
}
}
注意:
- 在接口的多重实现中 如果有同名的方法 只要实现一次即可
类可以继承的同时实现接口
class Students extends Person implements Ipic1,Ipic2{ }
匿名类
(实际上就是把一个没有命名的类赋给一个对象)
了解内容 PHP7.0支持
<?php
$stu = new class {
public $name = 'TOM';
function __construct(){
echo "这是一个构造方法";
}
};
echo $stu->name;
// 输出结果:这是一个构造方法TOM
好处:如果类只被实例化一次就可以使用匿名类 好处是实例化完毕后就回收了类的空间
方法绑定
了解内容 PHP7.0支持
作用:将方法绑定到对象上
语法:闭包->call(对象)
在PHP中匿名函数称为闭包
<?php
$lang = 'ch';
//类
class Student{}
// 匿名函数
if($lang == 'ch'){
$fun = function(){
echo '我是一名学生';
};
}else{
$fun = function(){
echo 'I am a student';
};
}
# 绑定方法
$stu = new Student;
$fun->call($stu);
// 我是一名学生
异常处理
集中处理在代码块中发生的异常
在代码块中发生了异常直接抛出,代码块中不处理异常,将异常集中起来一起处理
使用的关键字
try:检测代码块
catch:捕获异常
throw:抛出异常
finally:无论有无异常都会执行,可以省略
Exception:异常类
语法结构
try{
#检测代码
}catch(Exception $ex){
#捕获异常
}
finally{
#不论是否有异常 都要执行 finally可以省略
}
例题:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<?php
if (isset($_POST['button'])) {
try{
$age = $_POST['age'];
if ($age=="")
# 抛出异常
throw new Exception("年龄不能为空");
if(!is_numeric($age))
# 抛出异常
throw new Exception("年龄必须为数字");
if (!($age>=10 && $age<=30))
# 抛出异常
throw new Exception("年龄必须在10~30之间");
echo "您的年龄合适<br>";
}catch(Exception $ex){
#捕获异常
echo '错误信息:'.$ex->getMessage().'<br>';
echo '错误码:'.$ex->getCode().'<br>';
echo '文件地址:'.$ex->getFile().'<br>';
echo '错误信息:'.$ex->getLine().'<br>';
}finally{
#不管是否有异常,finally表示最终都要执行
echo "关闭数据库连接";
}
}
?>
<form action="" method="post">
年龄:<input type="text" name="age" id=""><br>
<input type="submit" name="button" value="提交">
</form>
</body>
</html>
注意:抛出异常后 try块终止执行 权限交给了catch块
自定义异常
场景:如果有实现异常的分类处理?比如异常有三个级别异常对应三种处理方式
自定义三种异常即可
所有异常类的父类是Expection,Exception中的方法不允许重写
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
<form action="" method="post" accept-charset="utf-8">
姓名:<input type="text" name="name" value="" placeholder=""><br>
年龄:<input type="text" name="age" value="" placeholder=""><br>
<input type="submit" name="submit" value="提交">
</form>
<?php
#自定义空异常类
class MyNullException extends Exception{
}
#自定义类型异常类
class MyTypeException extends Exception{
}
#自定义范围异常类
class MyRangeException extends Exception{
}
#逻辑代码
if (isset($_POST['submit'])) {
try{
$name = $_POST['name'];
$age = $_POST['age'];
#$age+=0;
var_dump($age);echo "<br>";
if ($name=="")
throw new MyNullException("姓名不能为空", 1);
if ($age=="")
throw new MyNullException("年龄不能为空", 2);
if (!is_numeric($age))
throw new MyTypeException("年龄不是数字", 3);
if ($age<10 || $age>30)
throw new MyRangeException("年龄必须在10~30之间", 4);
echo "姓名:".$name.'<br>';
echo "年龄:".$age.'<br>';
}catch(MyNullException $ex){
echo $ex->getMessage().'<br>';
echo "错误记录在日志中";
}catch(MyTypeException $ex){
echo $ex->getMessage();
echo "发送电子邮件";
}catch(MyRangeException $ex){
echo $ex->getMessage();
echo "给管理员打电话";
}
}
?>
</body>
</html>
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
Test for comments