文章目录
PDO面向对象编程
概述
-
面向对象编程是一种编程思想
-
面向对象编程是以事物(对象)为中心的编程思想
-
面向对象编程是以功能来划分问题,而不是步骤
类和对象的关系
- 类是具有相同属性和行为的一组对象的集合,它为属于类的全部对象提供了统一的抽象描述,其中内部包含属性和行为的两个部分。
- 类的两个要素:属性(Attribute)和行为(Behavior)
- 对象是类的实例,类是对象的模板
- 类是抽象的,几乎不占用内存,而对象是具体的,占用存储空间
类的定义
-
定义语法格式:
class 类名称{...}
- 关键字
class
- 关键字
-
属性 某个类具有公共的特征和特性,与普通变量的区别,类成员必须带权限修饰符。
- 方法 某个类的公共行为或动作,与普通函数的区别,类方法带权限修饰符,权限修饰符可以省略,默认值为
public
。 - 权限修饰符:public 、private、protected修饰
<?php //定义一个学生类 class Student{ public $name = "张三"; private $age =28; //构造函数 public function __construct(){ } //方法 public function showInfo(){ echo "{$this->name}的年龄是{$this->age}岁!"; } } ?>
- 方法 某个类的公共行为或动作,与普通函数的区别,类方法带权限修饰符,权限修饰符可以省略,默认值为
实例化对象
-
使用关键字
new
创建 -
实例: o b j = n e w S t u d e n t ( ) ; 或 obj = new Student();或 obj=newStudent();或obj = new Student;
-
访问对象属性和方法: o b j − > n a m e ; obj->name; obj−>name;obj->showInfo();
<?php $obj = new Student();//实例化对象 echo $obj->name;//调用属性 $obj->age会报权限不足,只有public修饰符修饰的属性或方法可以在外部调用 $obj->showInfo();//调用方法 ?>
对象属性操作
- 添加或赋值:对象->属性 = 值;如:
$obj->name = "李四";
存在的属性会重新赋值,不能操作的属性,会添加 - 删除属性:unset(对象->属性);如:
unset($obj->name);
- 读取属性:对象->属性;如:
$obj->name;
对象方法操作
- 调用:对象->方法();如:
$obj->showInfo();
$this关键字
- $this指当前实例化的对象,只能在对象内使用;
- $this是当前对象的一个引用
- 在方法内调用对象时,可以使用 t h i s 调 用 , 如 : ‘ this调用,如:` this调用,如:‘this->name`
- 只有创建对象后,$this变量才会存在,类不会自动调用。
__construct()构造方法
-
当使用new 实例化对象是,系统默认调用的第一个方法。
-
构造方法固定写法,
_construsct(){}
,类默认有一个参数为空的构造方法! -
作用:对象初始化,如给对象属性赋值
-
构造方法不需要手动调用,会自动被调用;
<?php class Student{ public $name; public $age; public $height; public function __construct($n,$a,$h){ $this->name = $n; $this—>age = $a; $this->height = $h; } public function showInfo(){ echo "<br>姓名:".$this->name; echo "<br>年龄:".$this->age."岁"; echo "<br>身高:".$this->height."cm"; } } $student = new Student('张三',20,172); $student->showInfo(); ?>
打印结果:
姓名:张三 年龄:20岁 身高:172cm
__destruct()析构方法
- 定义:对象销毁前自动调用的方法,方法名称是固定的
__destruct(void){}
- 作用:垃圾回收工作,释放内存,如断开Mysql数据库连接
- 执行时间:程序执行完毕时,对象会自动销毁;或使用unset删除对象时;
- 正常销毁执行是在网页执行完毕后,销毁对象时才会执行
__destruct()
- 如果使用
unset()
方法删除对象时,unset()
之后,会马上执行__destruct()
- 正常销毁执行是在网页执行完毕后,销毁对象时才会执行
类常量
-
类介绍
- 可以把类中始终保持不变的值定义为常量
- 常量的值必须是一个定值,不能修改,也不能删除
- 类常量是类的常量,是与类相关,与对象无关
- 类常量在内存中只有一份,不管创建多少个对象
- 类常量可以极大节约服务器内存,可以被所有对象共享
-
类常量的定义和调用格式
- 类常量没有权限
- 使用
const
来定义类的常量(局部常量),只能在类的局部作用域下使用。define()
定义的是全局变量,在任意地方可以使用
-
语法:const 常量名 = 常量值;
- 常量名建议全大写
- const定义的常量必须赋值
- 常量的值必须为定值
- 常量没有权限修饰符
- 常量调用:ClassName::常量名;(使用静态化调用)
- 注意:类常量不是变量,在使用是不能像变量一样在双引号中被解析,如果需要使用,请按一下方式
"班级名称为".Student::CLASSNAME
;
<?php class Student{ const CLASSNAME = "中一班"; public $name = "张三"; private $age = 4; } //访问 echo Student::CLASSNAME; ?>
静态属性和静态方法
-
关键值
static
修饰的属性或方法就是静态属性或方法 -
静态属性和静态方法时类的属性和方法,与对象无关
-
调用静态属性和静态方法,需要使用
类名::$属性
或类名::方法()
方式 -
静态属性或静态方法,在内存中只有一份,被所有对象共享。
-
静态属性和类常量的区别:类常量在一次http请求过程中值保持不变,但静态属性可以改变
-
静态属性和静态方法都可以加权限修饰符,类常量没有权限。
<?php class Student{ public function $count = 60; } echo Student::$count; ?>
self关键字
-
self是当前类的指针,$this是当前对象的指针
-
self用来调用类常量、静态属性和静态方法
-
与 t h i s 不 一 样 , this不一样, this不一样,this是调用对象的属性和方法,且$this关键字只能在成员方法中使用。
-
self可以在成员方法和静态方法中使用
-
static修饰的方法,不能出现$this
<?php class Student{ public $name = "张三"; public static $class_name = "中一班"; public static function test(){ echo self::$class_name; //echo $this->name;//错误调用 } } Student::test(); ?>
学生类实例
-
要求:定义一个学生类,该类包含姓名,性别,年龄等基本信息,并且至少包含一个静态属性和一个常量,以及包括构造方法和析构方法。该对象还可以调用一个方法来进行自我介绍,显示该学生对象的所有属性。构造方法可以自动初始化一个学生的基本信息,并显示’‘欢迎某某新同学加入中一班大家庭,当前班级共有xx个学生”。
<?php class Student{ const CLASS_NAME = '中一班';//类常量 private static $count = 0;//静态属性 private $name; private $age; private $sex; public function __construct($n,$a,$s){ $this->name = $n; $this->age = $a; $this->sex = $s; self::$count++; echo "<br>欢迎".$n."同学加入".self::CLASS_NAME."大家庭,当前班级人数为".self::$count; self::showInfo(); } public function showInfo(){ echo "<br>班级:".self::CLASS_NAME; echo "<br>姓名:".$this->name; echo "<br>年龄:".$this->age; echo "<br>性别:".$this->sex; } public function __destruct(){ } } $student = new Student('张三',4,'男'); $student2 = new Student('李四',3,'男'); ?>
-
输出结果
欢迎张三同学加入中一班大家庭,当前班级人数为1 班级:中一班 姓名:张三 年龄:4 性别:男 欢迎李四同学加入中一班大家庭,当前班级人数为2 班级:中一班 姓名:李四 年龄:3 性别:男
对象内存分布情况
-
分布
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WBfOv8Mx-1573031277933)(E:\学习笔记\PHP学习\images\opp内存分布情况.png)]
-
使用
var_dump()
打印对象时,只看到对象的属性;
对象属于引用传递
-
把对象赋值给另一个变量时,会把对象的引用地址赋予
<?php class Student{ public $name; public $age; public $sex; public function __construct($n,$a,$s){ $this->name = $n; $this->age = $a; $this->sex = $s; } } $student = new Student('张三',4,'男'); $student2 = $student; $student2->name = "李四"; echo "<pre>"; var_dump($student);
-
输出结果
object(Student)#1 (3) { ["name"]=> string(6) "李四" ["age"]=> int(4) ["sex"]=> string(3) "男" }
类的特性
类的三大特性封装、继承和多态
封装性
-
public 公共权限 在任意地方都可以调用,包括类内、类外、子类均可以调用
-
private 私有权限 只能在类中调用
-
protected 受保护的 类中和子类中可以条用,类外不能调用
-
简单实现数据库类连接
class Db{ //私有配置属性 private $db_host;//主机名 private $db_user;//用户名 private $db_pass;//密码 private $db_name;//数据库名称 private $charset;//字符集 private $link;//连接对象 //构造方法实现数据库对象初始化 public function __construct($config = array()){ $this->db_host = $config['db_host']; $this->db_user= $config['db_user']; $this->db_pass= $config['db_pass']; $this->db_name= $config['db_name']; $this->charset= $config['charset']; $this->connectDb();//连接数据库服务器 $this->selectDb();//选择数据库 $this->setCharset();//设置字符值 } //连接数据库 private function connectDb(){ if(!$this->link = @mysqli_connect($this->db_host,$this->db_user,$this->db_pass)){ echo "连接Mysql服务器失败"; die(); } } //选择数据库 private function selectDb(){ if(!mysqli_select_db($this->link,$this->db_name)){ echo "选择数据库失败"; die(); } } //设置字符在 private function setCharset(){ mysqli_set_charset($this->link,$this->charset); } //关闭数据库连接 public function __destruct(){ mysqli_close($this->link); } } $arr = array( 'db_host'=>'127.0.0.1', 'db_user'=>'root', 'db_pass'=>'root', 'db_name'=>'shitu', 'charset'=>'utf8', ); $db = new Db($arr); var_dump($db); ?>
继承性
-
关键字
extends
<?php class Student{ public $name; public $age; } class English extends Student{ public $className; } ?>
-
如果多个类拥有相同的属性和方法,可以把相同的属性和方法提取出来,放到一个 “父类”中,然后再创建子类通过
extends
关键字进行继承父类。 -
子类拥有父类中所属性和方法(除了private权限修饰符修饰的),子类中可以直接调入属性和方法;
-
子类可以扩展新功能和对父类中的功能进行完善,实现功能的升级和完善
-
类只能单继承,某一个子类有且只有一个直接父类;
parent 关键字
-
self代表当前类,parent代表父类
-
self用来调用本类的内容,包括:类常量、静态属性、静态方法、成员方法等
-
parent 用来调用父类的内容,包括:类常量、静态方法、静态属性和成员方法等
-
self 和 parent都是用范围解析符
::
来调用其内容 -
语法:parent::类常量 | 静态属性 | 静态方法 | 成员方法;
<?php class Student{ const TABEL = "学生"; protected $name; protected $age; } class PHPStudent extends Student{ const TABEL = "PHP学生"; public function showInfo(){ echo "<br>父类中的TABEL".parent::TABEL; echo "<br>本类中的TABEL".self::TABEL; } } $stu2 = new PHPStudent(); $stu2->showInfo(); ?>
多态性
- 子类进行同名方法重现,实现类的多种形态
- 方法重写要求:
- 与父类中的方法名同名
- 要求参数与父级的参数一样
- 与父类中同名方法类型一致 如:父类属于静态方法的子类也必须是静态的
- 子类重写的方法访问权限,不能低于父类的同名方法权限
- 父类方法权限为public时,子类的同名方法权限只能为public
- 父类方法权限为protected时,子类同名方法权限可以时public和protected
- 父类方法权限为private时,子类无法继承和重写
最终类和最终方法
- 关键字 final
- final关键字修饰的类,就是最终类,不能被继承
- final关键字修饰的方法,就是最终方法,不能被重写
- 最终类和最终方法不能同时用,因为最终类不能被继承,所有无法重写
抽象类和抽象方法
-
关键字 abstract
-
abstract 修饰的类,就是抽象类,该类不能直接实例化,必须先继承和重写抽象方法后才能实列化;
-
abstract修饰的方法,该方法存在与抽象类中,必须重写后才能使用;
- 注意:抽象方法,不能有方法体(即没有
{}
);
- 注意:抽象方法,不能有方法体(即没有
-
如果一个类中包含了抽象方法,则这个类必须是抽象类
-
在PHP7中,抽象方法可以是成员方法,也可以是静态方法,在PHP5的版本只能为成员方法·
-
抽象类中可以定义类的所有属性和方法,但必须包含一个或一个以上的抽象方法的
<?php //抽象类 abstract class Student{ const TABEL = "学生"; protected $name; protected $age; //抽象方法 public abstract function showInfo(); } class PHPStudent extends Student{ const TABEL = "PHP学生"; public function showInfo(){ echo "<br>父类中的TABEL".parent::TABEL; echo "<br>本类中的TABEL".self::TABEL; } } $stu2 = new PHPStudent(); $stu2->showInfo(); ?>
接口
-
关键字 interface 定义接口
-
关键字 implements 来实现接口
-
接口中方法权限必须为public
-
接口中所有方法默认为抽象的
-
接口中可以是静态方法也可以是成员方法
-
接口中可以定义常量,常量值不能被重写
-
类可以实现(implements)多个接口
-
接口也可以继承接口
<?php //学生接口 interface Student{ const TABEL = "学生"; public function showInfo();//权限必须为public } //实现接口 class PHPStudent implements Student{ //const TABEL = "PHP学生";//不能重写变量 public function showInfo(){ echo "<br>本类中的TABEL".self::TABEL; } } $stu2 = new PHPStudent(); $stu2->showInfo(); ?>
__clone()对象克隆
-
关键字 clone;
-
语法:
$obj2 = clone $obj2
; -
魔法方法:__clone() 会自动调用,可以在克隆过程中做一些操作
<?php class Student{ public $name = "张三"; public $age =28; public function showInfo(){ echo "<br>{$this->name}的年龄为{$this->age}岁"; } //克隆方法 public function __clone(){ $this->name = $this->name."_克隆"; $this->age = $this->age."_克隆"; } } $student = new Student(); $student2 = clone $student; var_dump($student); var_dump($student2); ?>
-
输出结果
object(Student)#1 (2) { ["name"]=> string(6) "张三" ["age"]=> int(28) } object(Student)#2 (2) { ["name"]=> string(13) "张三_克隆" ["age"]=> string(9) "28_克隆" }
foreach遍历对象
-
遍历对象会遍历对象的属性
class Student{ public $name = "张三"; public $age =28; public function showInfo(){ echo "<br>{$this->name}的年龄为{$this->age}岁"; } } $student = new Student(); foreach($student as $k => $v){ echo "<br>$v"; }
-
输出结果
张三 28
__toString()转字符串
-
把对象转成字符串时,__toString()会自动调用
-
语法 `public string __toString(void)
-
注意:PHP不支持对象转字符串,因此,不能使用echo 输出一个对象。
-
直接输出对象,系统会报语法错误,存在暴露服务器系统路径安全,因此一般使用__toString()屏蔽报错
**Recoverable fatal error**: Object of class Student could not be converted to string in **E:\rufeike\xdqphp\index.php** on line **23**
<?php class Student{ public $name = "张三"; public $age =28; public function showInfo(){ echo "<br>{$this->name}的年龄为{$this->age}岁"; } public function __toString(){ return "对象不能直接输出"; } } $student = new Student(); echo $student; ?>
输出结果
对象不能直接输出
__invoke()把对象当函数调用
-
描述:当把一个对象当成函数调用时,__invoike()会自动调用
-
当函数调用时,会报错
**Fatal error**: Uncaught Error: Function name must be a string in E:\rufeike\xdqphp\index.php:23 Stack trace: #0 {main} thrown in **E:\rufeike\xdqphp\index.php** on line **23**
<?php class Student{ public $name = "张三"; public $age =28; public function showInfo(){ echo "<br>{$this->name}的年龄为{$this->age}岁"; } public function __invoke(){ echo "对象不是函数,不能当函数调用"; } } $student = new Student(); $student(); ?>
输出结果:
对象不是函数,不能当函数调用
单例设置模式
-
描述:一个类只能创建一个实例对象
-
设置要求(三私一公):
- 私有的静态保存对象属性
- 私有的构造方法,防止类外部new对象
- 私有的克隆方法,防止类外部clone对象
- 公共的静态创建对象的方法
-
代码实现:
<php? class Db{ //私有的静态保存对象属性 private static $db = null; //私有的构造方法 private function __construct(){} //私有的克隆方法 private function __clone(){} //公共的静态创建对象方法 public static function getInstance(){ //判断当前对象是否存在 if(!self::$db instanceof self){ //如果对象不存在则创建对象 self::$db = new self(); } //存在则返回对象 return self::$db; } //防止直接输出对象 public function __toString(){ return "对象不能直接输出"; } //防止对象当函数调用 public function __invoke(){ echo "对象不能当函数使用"; } } $db = Db::getInstance(); $db2 = Db::getInstance(); var_dump($db); echo "<br>"; var_dump($db2); ?>
输出结果:
object(Db)#1 (0) { } object(Db)#1 (0) { }
工厂设置模式
-
描述:生产不同类对象的工厂。功能拓展和维护方便
-
传递不同的类名参数,返回不同类的对象
-
使用new 关键字创建对象的方式,改成工厂类中创建类的对象
-
主要实现思想,对功能和特性进行抽取 分成接口文件、实现类文件和工厂类文件以及应用类执行;
- 接口文件USB.interface.php
<?php interface USB{ public function run(); public function read(); public function write(); } ?>
- 实现类文件 USB1.class.php和USB2.class.php
<?php class USB1 implements USB{ public function run(){} public function read(){} public function write(){} } ?>
<?php class USB2 implements USB{ public function run(){} public function read(){} public function write(){} } ?>
- 工厂类Factory.class.php
<?php class Factory{ //对象创建方法 public static function getInstance($className){ //根据传递的不同类名参数,返回不同的类对象 switch($className){ case "USB1": return new USB1(); break; case "USB2": return new USB2(); default: return null; } } } ?>
- 应用文件index.php
<?php spl_autoload_register(function($className){ $classPath = '.\lib\'.$className.'.interface.php'; if(file_exists($classPath)){ require_once($classPath); }else{ die($classPath)不存在; } }) ?>
PHP重载
- PHP中所谓的重载,是指动态的创建类属性和方法,为了实现该功能。PHP官方提供了相关的魔术方法用于实现。
- 当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用
- 作用:该类方法可以屏蔽以下系统报错,也可以变相处理想要获取以下私有或受保护的内容
- 注意:
- 所有重载的方法,必须声明为public
- 属性重载只能再对象中进行,在静态方法中,这些魔术方法不会被调用。
- 魔术方法不能引用传递
__get()获取属性
- 描述:读取不可访问的属性的值时,__get()会被调用
- 语法:public mixed __get($var)
<?php
class Student{
private $name;
private $age;
public function __get($var){
echo "该".$var."属性为私有,不能访问";
}
}
$student = new Student();
echo $student->age;
?>
输出结果
该age属性为私有,不能访问
__set()设置属性
- 描述:给不可访问的属性赋值时,__set()会被调用
- 语法:public mixed __set($var)
- 作用:屏蔽报错,也可以个私有属性赋值
<?php
class Student{
private $name;
private $age;
public function __set($var){
$this->age = $var;
}
}
$student = new Student();
echo $student->age=10;
?>
__unset()删除属性
- 描述:删除不可访问的属性时,__unset()会被调用
- 删除私有属性和屏蔽错误
<?php
class Student{
private $name;
private $age;
public function __unset($var){
if(isset($this->$var)){
unset($this->$var);
}
}
}
$student = new Student();
unset($student->age);
?>
__isset()属性是否存在
- 描述:对不存在或不可访问的属性调用isset()或empty()时,__isset()会被调用
- 语法:public mixed __isset($var)
- 作用:屏蔽报错和判断是否存在私有属性
<?php
class Student{
private $name;
private $age;
public function __isset($var){
if(isset($this->$var)){
return true;
}else{
return false;
}
}
}
$student = new Student();
isset($student->age);
?>
__call()调用方法
- 描述:当访问不存在或不可访问的方法时,__call()会被调用
- 接收两个参数 __call( f u n c , func, func,args)
- 屏蔽错误或做其他处理
<?php
class Student{
private $name;
private $age;
public function __call($func,$args){
//处理代码
}
}
$student = new Student();
$student->showInfo();
?>
__callStatic()调用静态方法
- 描述:用静态方式当访问不存在或不可访问的方法时,__callStatic()会被调用
- 接收两个参数 __call( f u n c , func, func,args)
- 屏蔽错误或做其他处理
<?php
class Student{
private $name;
private $age;
public function __callStatic($func,$args){
//处理代码
}
}
$student = new Student();
$student::showInfo();
?>