PHP-OOP面向对象

2.面向对象

1.类简介

主要内容包括 类 和 对象

1.类

​ class类中主要两种元素,函数(方法),变量(属性)

​ 函数不调用不执行功能,类不实例化为对象无法使用

  1. 设计类的时候,需要考虑什么:(一切皆对象)

    该类有什么(属性)?

    该类会什么(方法)?

  2. 注意:

    • 类本身是无法执行的,本身是虚构的,不存在的
    • 对象才是真正能使用的
  3. 类与对象之间的关系

    • 类 就是对象的抽象化
    • 对象 就是类的实例化
  4. 格式

1
2
3
4
5
6
class 类名
{
成员属性
成员方法
}

6.实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Beauty
{
public $name = '迪丽热巴'; #属性
public $age = 18;
public $weight = '90斤';
public $height = '180cm';

public function skill1() #方法
{
echo '吹';
}
public function skill2()
{
echo '拉';
}
public function skill3()
{
echo '弹';
}
public function skill4()
{
echo '唱';
}
}

$obj = new Beauty; #实例化

echo $obj->name; #对象 -> 属性名
echo $obj->height;
echo $obj->weight;

$obj->skill1(); #对象 -> 方法名()
$obj->skill2();
$obj->skill3();

总结:

​ 1、在使用之前,要先将类实例化为对象,即:类->对象

$对象名 = new 类名;

​ 2、输出属性时,格式为:对象 -> 属性名

echo $obj->name;

​ 3、调用方法时,格式为:对象 -> 方法名()

$obj->skill();

2.伪对象

1.定义

​ 在类的内部,可以使用自己的属性or方法,此时, $this 代表当前对象

称为伪对象

2.实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Beauty
{
public $name = '迪丽热巴';
public $age = 18;
public $weight = '90斤';
public $height = '180cm';
public function skill1(){echo '吹';}
public function skill2(){echo '拉';}
public function skill3(){echo '弹';}
public function skill4(){echo '唱';}
public function demo(){
// 类的内部, 使用自己的属性or方法
$x = new Beauty;
echo $x->name;
$x->skill4();
echo '<hr>';

echo $this->name;
$this->skill4();
echo '<hr>';
}
}
}

总结:

​ 伪对象$this 代表当前对象, 在哪个类中使用, 就相当于$this = new 当前类名

$this 不需要实例化, 可直接使用.

$this 只能在类内使用

3.连贯操作

​ 若要在执行时连续调用方法,可采用如下格式:

​ 1. $obj->step1()->step2()->step3()...;

​ 2.将连续调用的前面的方法加上return $this

注意:若直接采用1,而不return返回对象,会报错 Call to a member function step2() on null 相当于null->step2()

4.魔术方法

1.定义:

​ 魔术方法,就是在指定条件触发时,会自动调用的方法,这里主要介绍两种

__construct() 构造方法

__destruct() 析构方法

2.构造方法

​ 触发条件:在实例化时,自动触发

​ 使用场合:常用于初始化属性

​ 注意:一般构造都写在方法的最前面,属性的最后面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Lengend
{
#构造方法
public function __construct()
{
echo '<h1>欢迎来到召唤师峡谷</h1>';
}
#普通方法
public function demo()
{
echo '升段局,掉2挂1,人马加大树强撑40分钟,队友重连绝地翻盘<hr>';
}
}

$obj=new Lengend;
$obj->__construct();
// $obj->demo();

3.析构方法

​ 触发条件:当对象被销毁时,自动触发,包括:

​ 1).程序全部执行完,自然销毁

​ 2).对象被主动删除了

​ 3).对象被覆盖了(更换)

​ 使用场合:当对象使用完的一些扫尾操作(fclose、closedir)

​ 注意:一般析构方法都写在方法的最后面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Lengend
{
public function demo()
{
echo '开始一盘游戏';
echo '<hr>';
}
public function __destruct()
{
echo '关上电脑';
}
}
$obj=new Lengend;
$obj->demo();
echo '断电了<br>';

unset($obj); #2)对象被主动删除

$obj='迪丽热巴'; #3)换对象了
#1)自然结束,就会销毁$obj,从而触发析构

4.实例化PDO类

​ PDO 数据抽象层,专门负责数据库操作管理

1
2
3
4
5
6
7
8
9
$dsn='mysql:host=localhost;dbname='test';charset=utf8;
$user='root';
$pwd='';
$pdo=new PDO($dsn,$user,$pwd); #1.链接数据库
$sql='select id,nickname,tel,address from user'; #2.编写sql语句
$pdostatement=$pdo->query($sql); #3.执行sql语句
$result=$pdostatement->fetchAll(PDO::FETCH_NUM); #4.解析对象
var_dump($result); #5.输出结果

总结:

​ 1.PDO类::方法

  • PDO::query( ) 执行一条SQL语句

    成功返回PSOStatement,适合查询,失败返回false

  • PDO::exec( ) 执行一条SQL语句

    成功返回受影响的行数,适合增删改,失败返回false

  • PDO::lastInsertId( ) 获取最近一次插入的ID

    成功返回最新的id,失败返回 '0' 字符

  • PDO::errorInfo( ) 获取错误信息

​ 2.PDOStatement类::方法

  • PDOStatement::fetch( ) 获取结果集中的一条数据(依靠指针)失败返回false
  • PDOStatement::fetchAll( ) 获取结果集中的所有数据,参数设置显示格式
    • PDO::FETCH_NUM 索引数组格式
    • PDO::FETCH_ASSOC 关联数组格式
    • PDO::FETCH_BOTH 混合数组格式

3.OOP面向对象

面向对象OOP的三大特性:1.封装性 ;2.继承性 ;3.多态性

1.封装性

  • 定义:将对象的所有成员结合在一起,形成一个不可分割的独立单位

  • 目的:尽可能的隐藏属性 和 方法,只留下部分接口与外部联系

  • 提供以下三种修饰符,来控制与外部的联系

    修饰符 本类 继承类 类外
    public 公有的
    protected x 受保护的
    private x x 私有的

    想要有高安全性 或者 只想自己使用的,最好设置为private。

2.魔术方法

如果在类外使用私有属性或方法,程序会立即终止并报错

为了避免终止程序,可以使用一些魔术方法做提示,并绕过error错误

  • __get($x)

    当访问权限不足或不存在的属性时,自动触发,返回访问属性名

  • __set($x,$y)

    当设置权限不足或不存在的属性时,自动触发,返回设置属性名和值

  • __unset($x)

    当删除权限不足或不存在的属性时,自动触发,返回要删除的属性名

  • __isset($x)

    当判断是否存在的目标权限不足或不存在时触发,返回要判断的属性名

  • __call($x,$y)

    当访问权限不足或不存在的方法时,自动触发,返回方法名和实参

  • __tostring()

    当echo对象时触发,返回字符串值

3.继承性

  1. 定义:子类(-派生类/扩展类)继承父类(基础类/基类)的一些属性和方法

  2. 格式

    class 子类 extends 父类 {}

  3. 实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class laozi
    {
    public $name = '老王';
    public function skill()
    {
    echo '喜欢去隔壁转转 <br>';
    }
    }
    class son extends laozi
    {
    }
    $obj = new son; #实例化子类
    echo $obj->name; #直接调用子类继承的属性
    $obj->skill(); #直接调用子类继承的方法


  4. 特点

  • 子类可以继承属性,方法(除了private)

  • 子类可以重写属性,方法

  • 子类可以扩展方法 parent::父级方法名

  • 访问级别:

    private>protected>public

    子类继承父类时,修饰符可以保留等级,可以降级,就是不能升级

  1. 继承方式
    1. 单继承(一个子级可以继承一个父级)
    2. 连续继承(爷->父->子->孙 依次继承)
    3. 多继承(无法在PHP中实现)

4.类静态

1.关键字:

static

2.格式:

static 修饰符 $属性名=属性值;

static 修饰符 function 方法名(){};

3.使用格式:

类名::静态属性名 / 类名::静态方法名()

​ self 代表当前的类名,只能在类内使用

​ $this 代表当前的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
class Beauty
{
static public $name = '小张'; #设置静态属性
// public $age = 18; #静态类内不能使用非静态属性
static public function demo() #设置静态方法
{
echo 'i am static demo <hr>';
echo self::$name; #类内调用静态属性
echo '<hr>';
}
}
Beauty::demo(); #引用静态方法

4.特性:

  • 静态属性或方法 不需要实例化就可以直接使用
  • 静态方法内部只能使用静态属性或方法
  • 静态属性和方法可以继承

5.魔术方法

__callStatic($x,$y)

​ 在访问不存在的静态方法时,自动触发,返回静态方法名和实参

5.类常量

1.格式

const 类常量名=值;

2.使用类常量

类名::类常量

3.特性

  • 类常量可以继承,且可以重写一次
  • 普通常量可以直接在类内使用(常量没有作用域)
  • 类常量不能直接在类外使用,必须要通过类名来使用
1
2
3
4
5
6
7
8
9
10
11
12
const NAME = '黑寡妇';
class Beauty
{
const SEX = '美女'; #定义类常量
public function demo()
{
echo self::SEX;
echo NAME; # 直接输出类外的 普通常量NAME
}
}
echo Beauty::SEX; #输出类内常量

6.最终 final

1.使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
final class Beauty		#final 修饰类,保护不被继承
{
public $name = '陈琳琳';
}
------------------------------------------------------
class Father
{
final public function Order() #final修饰方法
{
echo '这是祖辈留下的祖训: 不能吃猪肉 <br>';
}
}

2.特性

  • final 可以修饰类和方法,不能修饰属性
  • final 修饰类,保护类不被继承
  • final 修饰方法,保护方法不被继承方法重写

7.克隆对象 clone

1.格式

副本对象 = clone 样本对象;

2.使用

1
2
3
4
5
6
7
8
class Beauty
{
public $name = '米拉乔沃维奇';
}

$a = new Beauty; #创建一个对象
$b = clone $a; #克隆对象

3.特性

​ 副本与样本对象完全一样,却互不影响,完全独立

克隆(clone)与复制出来的对象不一样,修改克隆副本对原样本没有任何影响,而修改复制对象则会影响原样本,相同点是删除副本对原样本都没有影响,原因如下:

​ 变量与内存是通过标识来引用的;

​ 删除原样本,只是删除元样本和标识之间 的联系,与复制副本无关;

​ 息息相关的只是内存的内容

4.克隆魔术方法

1.函数:

__clone()

2.作用:

​ 克隆操作时触发,可以为克隆副本重新初始化属性

3.实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Demo
{
public $name='kamora';
public function __clone()
{
$this->name='kamora2'; #克隆对象重写
}
}

$a=new Demo;
$b=clone $a; #克隆操作

var_dump($a,$b);

8.串行化/序列化

1.函数

​ 串行化: serialize( )

​ 反串行化: unserialize( )

2.目的

​ 将对象串行化为字符串

3.使用场景

​ 传参,存入文本,存数据库 …

4.实例

1
2
3
4
5
6
7
8
$obj=new Game;			#创建一个对象
$str= serialize($obj); #串行化对象,存入变量
file_put_contents('./save.txt',$str); #将变量内容存入文件

$newStr=file_get_contents('./save.txt'); #读取文件内容
$newObj=unserialize($newStr); #对读取内容反串行化
$newObj->skill(); #使用对象属性方法

5.串行化魔术方法

1.函数:
  • __sleep( )

​ serialize串行化时触发,用以返回需要的信息(数组形式)

  • __wakeup( )

    unserialize反串行化时触发, 用以重新初始化属性

2.应用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Game
{
public $name = 'DNF';
public $money = 200000;
public function skill()
{
echo '崩山斩';
}
public function __sleep()
{
// 返回需要显示的信息(以数组形式返回)
return ['name','nickname'];
} //其余信息隐藏,实际上还是存在

public function __wakeup()
{
// 在唤醒时, 重新初始化属性
$this->money = 2;
}
}

9.魔术方法—自动加载

在真实项目中 , 一个PHP文件内 , 只有一个类 , 没有多余的代码,可以在多PHP相互加载的状态下的纯PHP界面省略定界符<?= ?> 中的后面部分,需要引入的HTML文件使用 include / include 加载

1.格式

1
2
3
4
5
function __autoload($x)
{

}

2.作用 :

​ 在实例化一个不存在的类时 , 自动触发 , 返回要求实例化的类名

3.使用场景 :

​ 使用数据库功能 , 上传文件功能 , 图形验证码功能等….

4.实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
一次性加载所有的类文件:
function __autoload()
{ #如果相关类文件存在
if( file_exists("./Model/{$x}.php") ){
include "./Model/{$x}.php";
}else{
header('location:404.php'); #跳转到404页面
die;
}
}
$a=new DB; #实例化数据库类
$b=new Upload; #实例化上传类


10.抽象

1.抽象

抽象方法 : 没有方法体( 代码块 ) 的方法

抽象类 : 包含抽象方法的类

1.关键字

abstract

2.特性

  • 包含抽象方法的类必须为抽象类
  • 抽象类不一定需要包含抽象方法
  • 抽象类不能被实例化
  • 抽象类必须被子类继承 , 并实现抽象方法

3.目的

​ 强制约束子类继承并实现抽象方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   abstract class Demo			#定义抽象类
{
public function func1()
{
echo '该项目已经完成了 20% <br>';
}
abstract public function func2(); #定义抽象方法
}
class Friend extends Demo #子类继承抽象类
{
public function func2() #子类事项抽象方法
{
echo '该项目已经完成了 30% <br>';
}
}
$obj = new Friend; #实例化子类,调用方法

2.接口

1.定义

​ 当类中全部都是抽象方法时,可定义为接口

​ 即接口就是抽象类( 条件 : 内部方法全部为抽象方法 )

2.特性

​ 接口继承是通过 implements 关键字继承的 (不是extends)

​ 接口可以实现多继承( 可以有多个父类,分别实现各个父类继承的抽象方法 )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
   interface Demo	#定义接口Demo
{
public function func1(); #内部方法全部为抽象方法
public function func2();
public function func3();
}
class Friend implements Demo #子类继承Demo
{
public function func1() #子类实现继承的抽象方法
{
echo '该项目已经完成了 20% <br>';
}

public function func2()
{
echo '该项目已经完成了 50% <br>';
}

public function func3()
{
echo '该项目已经完成了 30% <br>';
}
}
$obj = new Friend; #实例化子类
$obj->func1(); #调用Demo方法

3.类型约束

PHP支持的函数实参类型约束有数组对象

格式 : 方法名( 类名 变量 )|方法名( array 变量 )

1
2
3
4
5
6
7
8
9
function demo(array $x)	#约束送入的实参只能是数组类型
{
var_dump($x);
}

// demo($a=100); #送入整型数据程序报错
$b = [10,20,30];
demo($b); #送入数组,正常输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Demo1 {}

class Demo2
{
public function Test(Demo1 $x) #要求送入Demo1对象
{
var_dump($x);
}
}

class Demo3 {}

$demo1 = new Demo1; #实例化类,得到对象
$demo2 = new Demo2;
$demo3 = new Demo3;

$demo2->Test($var=100); #送入整型数据,程序报错
$demo1->Test($demo1); #送入demo1,正常输出

4.接口多态性

多态性 : 通过同一个接口 [ 抽象类|普通类 ] ,传入不同的设备,从而实现不同的效果

( 普通类没有强制约束子类执行指定方法的特征 , 不推荐使用 )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
interface USB		#定义接口
{
public function run();
} #指定抽象方法,一旦实现USB必须执行run方法
class Mouse implements USB #继承抽象类
{
public function run() #实现抽象方法
{
echo '安装鼠标驱动';
}
public function double() #扩展接入接口的子类方法
{
echo '双击功能实现';
}
}
class Keyboard implements USB
{
public function run()
{
echo '安装键盘驱动';
}
public function click()
{
echo '击键功能实现';
}
}
class Computer #设置接口使用环境
{
public function Start(USB $x) #接入接口
{
$x->run();
}
}

$c=new Computer; #实例化
$m=new Mouse;
$k=new Keyboard;

$c->start($m); #依接入类型运行接口方法
$c->start($k); #?如何使用double()

5.foreach遍历对象

foreach不但能够遍历数组,也可以遍历对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Book
{
public $name; #成员属性只能定义,不赋初值
public $price;
private $author;
public function __construct($a,$b,$c) #初始化属性
{
$this->name = $a;
$this->price= $b;
$this->author=$c;
}
$zhang=new Book('《新三国》','30元','小飞');
$cheng=new Book('《旧三国》','50元','阿亮');
} #类外依旧受修饰符影响
foreach($zhang as $key => $value){
echo $key.'------'.$value.'<br>';
}
foreach($cheng as $key => $value){
echo $key.'------'.$value.'<br>';
}

注意: 遍历对象是将对象中的 ( 属性名=>属性值 ) 遍历显示

6.对象相关函数

  • 判断类是否存在

    class_exists( '类名' ) 返回bool值

  • 判断某个类下的属性是否存在

    property_exists( '类名','属性名' ) 返回bool值

    可以检测私有属性,但不显示具体值

  • 获取类中的所有公有属性

    get_class_vars( '类名' ) 返回数组, 包含属性名和属性值

  • 获取对象中的所有公有属性

    get_object_vars( '对象' ) 返回数组, 包含属性名和属性值

  • 获取类中的所有公有方法

    get_class_method( '类名' ) 返回索引数组, 包含所有方法名

  • 获取某个对象的类名

    get_class( '对象' ) 返回字符串, 类名