PHP面向对象
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP面向对象相关的知识,希望对你有一定的参考价值。
构造方法 __construct()
语法: 构造方法是在一个对象“出生”的时候自动调用的
析构方法 __destruct()
语法: 析构方法是在一个对象“消失”的时候自动调用的
作用: 在于释放对象所占用的额外的资源,而不是删除对象本身
注意:析构方法不能有任何的形参
对象的消失有几种情况:
1, 明确的使用unset删除一个对象变量
2,脚本程序运行结束后,所有的资源自动销毁(包括对象变量)
3,改变对象变量的值,也自动销毁
常见的删除对象的一种方式:$对象变量名 = NULL;
构造方法和析构方法的特点:
1, 都是以__开头
2, 都是由系统自动调用
3, 都是在某个特定的情况发生的时候,才自动调用!
__clone方法
instanceof运算符 作用就是判断一个对象是否为某一个类的一个实例!
语法为: 对象变量 instanceof 类名 返回一个布尔值!
静态方法 所谓的静态方法,就是所有的对象所共享的方法,从语法上看,也是由类来进行管理!
就是在声明的时候,前面加上关键字 static 即可
静态方法和非静态方法的区别:
它们二者之间的主要区别在于逻辑上的含义不一样:
静态方法:是指各个对象所共享的方法
非静态方法:是指各个对象独自占用的方法
无论采用什么方式调用静态方法,里面都不可以使用$this关键字,因为$this本身就体现了各个对象“独自”占用方法的含义! 要想使用$this关键字,只能调用非静态方法!
所以: 类调用静态成员,对象调用非静态成员!
类常量
指类内定义的常量,和普通的常量基本没有什么本质的区别,只是类常量都属于某一个类,只是类常量需要找到类才能访问!
定义 语法形式: const 常量名=值;
访问 语法形式: 类名::常量名
类中的所有的成员
一共有5种:
非静态属性
静态属性
非静态方法
静态方法
类常量
它们在内存中的存储机制如下:
类文件的自动加载
__autoload()
php在执行的时候,如果发现需要一个类(只要是和这个类相关的任何操作),而此时,当前执行脚本又没有该类的定义代码,也没有将该类的类文件加载进来!那么,PHP首先会自动的调用一个名字叫作__autoload()的函数!并且会给该函数传递一个参数,该参数就是当前需要的类的类名
自动加载的主要技巧是:类名一定要有类的定义文件要有关联,也就是说,我们能够通过类名找到该类的定义文件(类文件)!
注册其他的自动加载函数
spl_autoload_register(‘函数名’);
一般的,系统默认的自动加载函数就是__autoload(),但是,随着项目的不断扩大,有可能出现多个自动加载函数,比如被加载的文件里面又有__auload函数!
第一步:定义一个可以加载类文件的普通函数
第二步:将该普通函数注册成自动加载函数
注意:
1,函数的注册一定要发生在需要某个类之前!
2,可以注册多个自动加载函数,在载入成功之前,会依次按注册的顺序执行,直到找到为止
3,如果注册了其他的自动加载函数,那么系统默认的自动加载函数就失效了。 如果想继续使用__autoload()需要像注册其他普通函数一样,重新注册
注册非静态自动加载方法
spl_autoload_register(array(对象变量,“非静态方法名”))
注册静态自动加载方法
1,spl_autoload_register(array(‘类名‘,‘静态方法名‘))
2, spl_autoload_register("类名::静态方法名")
数据的序列化与反序列化
也叫作对象的串行化!
对象也是一种数据类型,既然是数据,就存在在被持久化存储的问题!
数据的存储 也就是数据被持久化,一般的,可以将数据存放到文件或数据库里面!
因为当PHP脚本执行结束之后,内存中所有的相关数据都会丢失,所以,如果想实现数据的持久化存储,应该在脚本运行结束之前进行持久化!
以保存到文件中为例:
向文件写入数据: file_put_contents(文件地址, 写入的数据),返回值是写入的字符串的字节长度!
从文件读取数据: file_get_contents(文件地址)
序列化: serialize(),将原始数据转换为可以用于保存和传输的字符串数据
反序列化: unserialize(),将序列化之后的字符串数据,转换为原始数据
注意:数据的序列化与反序列化适用于除了资源型以外的任何数据,包括对象和字符串本身!
因为资源型数据都是外部数据,而外部数据的环境随时都在发生改变,所以,持久化(序列化)一个资源型的数据毫无意义!
封装mysql类
以操作封装好的上面mysql.class.php类文件为例
序列化:
存储:
反序列化:
对象的序列化与反序列化
__sleep()
触发时机:在序列化一个对象的时候,由系统自动触发执行!
作用:该方法用于规定哪些属性需要被序列化,实现的方式为:返回一个索引数组,数组内的元素为需要被序列化的属性名的集合!
以操作封装好的上面mysql.class.php类文件为例
__wakeup()
触发时机:在一个对象反序列化的时候,由系统自动触发执行!
作用:在反序列化一个对象的时候,完成该对象的初始化工作!
以操作封装好的上面mysql.class.php类文件为例
类的继承
面向对象的三大特性:封装性、继承性、多态性!
继承的关键字:extends
继承:一个类从另一个已有的类获得其成员和特征,就叫作继承
派生:从一个已有的类产生一个新的类,称之为“派生”
所以,继承和派生只是从不同的方向看的两个相同的概念,比如A类派生出了B类,那么B类就继承自A类!
父类:也叫作基类,就是指已有的被继承的类
子类:也叫作派生类或者叫作扩展类
扩展:在子类中增加一些自己特有的特征信息(新的类成员),没有扩展,继承也就没有任何的意义!
单继承:也就是说,PHP中的一个类只能继承自一个其它的类,不能同时继承多个类,单继承也是大多数面向对象语言的特性!(C++就支持多继承)
注:属性和方法都可以被继承
继承的本质,不是把父类中的代码复制到子类内部,而是通过继承链条,找到相应的成员!
重写 override
基本概念 重写也叫作覆盖,就是当子类成员与父类成员名字相同的时候,从父类继承下来的成员会重新定义!
重写的本质还是由继承链链条决定的
注意:
此时父类中的同名方法还是存在的!只是找不到了!
parent关键字
相对于self代表的当前类的类名,parent关键字代表一个类的父类:
访问控制修饰符
所谓的访问控制修饰符,就是控制类的成员,在哪些地方可以访问,在哪些地方不能被访问的机制!(类比变量的作用域)
在PHP中,类中的成员一共有三个访问范围的概念:
当前类内: 当前代码所在的类内
继承链类内: 所有在一个继承链上的类内,它们的访问范围是一样的!
类外: 除了类内,都是类外
public: 公共的,当前类内,继承链类内和类外都可以被访问到,访问范围是最大的!
protected:受保护的,当前类内和继承链类内可以被访问到,类外不能访问!
private: 私有的,只有当前类内可以被访问到,其他类内和类外都不能访问!
访问控制修饰符的几点注意
1,当子类重写父类成员的时候,子类成员的访问控制修饰符的访问范围不应该低于父类的访问控制权限!
父类public 子类:只能是public
父类protected 子类:可以是 protected,也可以是public
2,私有属性和私有方法都不能被重写或覆盖,此时,子类中的同名成员可以当成子类中自身的新的成员!
多行多列:fetchAll(先执行SQL语句得到一个资源结果集,然后定义一个空数组,然后配合while循环和mysql_fetch_assoc语句一个一个将结果提取出来)
一行多列:fetchRow
单行单列:fetchColumn
最终类final
final类的意义
如果某个类从业务逻辑的角度看,应该是最终的类别,不应该再继续派生出其他的子类了,此时就应该使用关键字final将该类声明为“最终类”
最终方法 final method 所谓的最终方法,就是从语法上规定不能被子类重写的方法:
在一个方法名的前面加上final关键字,就变成了一个最终方法!
注意:
当一个类可以被继承的时候,最终方法才有意义!
最终类里面的最终方法是没有意义的!
abstract抽象类
概念 只能被继承,不能实例化对象的类叫作抽象类!
声明 体现在代码上,需要在类名的前面加上abstract关键字,定义抽象方法的方式就是在方法名的前面加上abstract关键字然后此时该方法就不应该完善方法体!等待期下一级的子类去完善!
如果一个类继承了该抽象类,也只有两种选择:
要么实现该抽象类中抽象方法的方法体!
要么继续做抽象类!
抽象类的作用
1, 可以完成普通类的继承,为其他的类提供公共的代码!以前普通类中出现的成员都可以出现在抽象类中,也都可以被其他子类所继承!
2, 用于规定子类中必须要实现的方法,规定子类的方法结构,有时候为了保证完成一系列功能相似的多种操作类的结构保持一致,我们需要要求该系列类都继承自同一个抽象类!所以,抽象类更多的时候,也是作为一种语法上的规范!
interface接口
接口就是一个对象对外的公共的操作方法(必须为public)
接口的定义 是通过关键字interface来定义的:
注意:接口不是类,只是类的一种规范!接口就是一种纯粹的规范或者规定,规定“实现”该接口的下级类必须要实现的公共的方法!
在一个接口中,只能出现两种成员:
接口常量:其实普通的常量,只不过是出现在一个接口中而已!
抽象方法:必须声明为public(与抽象类不同,抽象类还可以声明为protected)
如果要使该接口作用到类上面,就要使用implements关键字,意思为“实现”,其实和继承的本质是一样的!
当一个类“实现”一个接口的时候,也只有两种选择:
1, 实现该接口中所有的公共的抽象方法(完善方法体)
如果该类中没有实现接口的部分或全部抽象方法,只能将该类声明为抽象类!等待更下一级的类去实现!
接口与抽象类的比较
1, 从逻辑上看,接口可以看成是抽象类的一个“子集”,比抽象类更“抽象”
2, 都可以规定下级类的内部结构,不过接口只能规定下级类的内部结构,更是类的纯粹的一种规范(接口不是类,是类的规范,类又是对象的规范)
3, PHP不支持多继承,但是支持多实现,也就说,一个类可以同时实现多个接口,这也是抽象类与接口的最本质的区别!
4, 如果一个类实现了多个接口,要么就实现所有接口的抽象方法,要么就只能做抽象类!
overload重载
PHP中的重载 指的是对不可访问的成员的处理方式,称之为成员的重载(包括属性重载和方法重载)
不可访问有哪些情况?
1, 该成员就不存在(没有定义)
2, 没有权限方法(受访问控制修饰符的限制)
属性重载
关于属性重载,是通过php所提供的魔术方法来完成的!
一共有4个,分别处理属性操作的4种情况:
为不可访问的属性赋值的时候 __set()
获得不可访问的属性的值的时候 __get()
删除不可访问的属性的时候 __unset()
判断不可访问的属性是否存在的时候 __isset()
__set()
触发时机:为一个不可访问的属性赋值的时候!
作用:系统默认的是行为是允许将一个不存在的属性重新载入到一个类的内部,但是,一旦定义了__set()这个魔术方法,处理权就交给用户自己了!
应该有两个参数:
一个是该属性的属性名
一个是给该属性赋的值
__get()
触发时机:当获取一个不可访问的属性的值的时候!
作用:系统默认的是行为是报告一个Notice级别的错误,但是,一旦定义了__get()这个魔术方法,处理权就交给用户自己了!
该魔术方法只需要一个参数,就是这个不可访问的属性的名字
注意:
__set()和__get()往往是成对出现的!在实际的开发中,往往利用它们批量的对对象的私有属性进行处理!
__unset()
触发时机:删除一个不可访问的属性的时候
作用:系统默认的行为是报错,如果加入了__unset方法,此时决定权就在用户自己了!
该魔术方法也只需要一个参数,就是这个不可访问的属性的名字!
_isset()
触发时机:当判断一个不可访问的成员是否存在的时候
作用:系统默认的行为是返回false,但是一旦加入了__isset魔术方法,决定权又交给用户了!
该魔术方法同样只需要一个参数,就是那个不可访问的属性的名字
方法重载
处理不可访问的方法的时候的处理方式!
利用两个魔术方法来完成:
__call()
__callstatic()
__call()
当调用一个不可访问的非静态方法(对象方法)的时候,会自动执行该魔术方法!
系统默认的行为是报错:
__call方法需要两个参数 :方法名:string 型参数列表:array型
_callstatic()
触发时机:当访问一个不可访问的静态方法的时候,会自动执行该方法!注意:需要在该方法的前面加上static关键字!因为,当访问的静态方法不存在的时候,也应该由类来访问这个魔术方法,所以需要加上static关键字!
__invoke()
触发时机:当把对象当做一个函数或方法来调用的时候,会自动执行该魔术方法!目前用的不是太多!
调用匿名函数的过程其实就是把一个对象当成一个函数来调用的过程!
之所以能调用成功,就是因为闭包对象里面包含了__invoke魔术方法!
__toString()
触发时机:将一个对象当做一个字符串来使用的时候,会自动触发该方法!
__CLASS__
代表当前类名
__METHOD__
代表当前的方法名!
后期静态绑定
目前代表类的关键字一共有三个:
self:当前类,绑定的时机在预编译阶段!
parent:父类!
static:当前类,绑定的实际在运行阶段!
以上是关于PHP面向对象的主要内容,如果未能解决你的问题,请参考以下文章