首页 > 代码库 > 访问修饰限定符的简单总结、final/abstruct/interface对类的限制、自动加载机制、序列化与反序列化【数据持久化和对象的序列化问题】、对象的拷贝(按引用是因为对象标识)和克隆(__clone方法中的this指向)

访问修饰限定符的简单总结、final/abstruct/interface对类的限制、自动加载机制、序列化与反序列化【数据持久化和对象的序列化问题】、对象的拷贝(按引用是因为对象标识)和克隆(__clone方法中的this指向)

1.针对访问修饰限定符的理解只需要两点:
(1)针对的是类的概念和访问代码的位置来确定是否能够访问
(2)对访问修饰限定符的使用时只需要对该成员的使用场景注意即可【也就是内部,继承类,外部进行访问的权限】

不需要对内部进行太多理解
【需要对php底层理解时进行理解】

【重点】
【用途】
通过访问修饰限定符将内部成员的权限合理的限制,然后再使用公共接口来调用这个基本服务,保证外部不能访问其内部的构件
【这样既能够通过类内的设置,将内部的功能实现更好的限制,只有最外层的接口可以正常被访问到,而不了解内部的业务】


【设置权限时的原则:设计框架时的考虑原则】
【禁用所有,开放特殊】
【在某方法被调用超过两次就可以考虑该方法被单独提取出来进行调用处理】


2.final类【不能被继承,只能被实例化对象】
类的作用:
(1)对象在定义之初的控制
(2)调用其静态成员
(3)作为其他类的基础类,被继承

两大功能
(1)实例化对象
(2)被继承


存在两种特殊的类,功能单一
(1)一种只能实例化对象【不能被继承final类】
(2)只能被继承【不能实例化对象抽象类abstract】

final类:
在继承链条上,最末的一个类【保证不被继承】
在语法上限制某个类不能被继承。【来实现final类需要的效果】

final类的使用就是为了将该类限制不被继承而只能被实例化来实现的途径来实现特殊的类。

 

3.抽象类abstract类
抽象类指的是不完整的类。【由于包含了不完整的方法所以被称为不完整类】(这也就是为何抽象方法一旦存在,那么这个类就是抽象类)
不完整方法【抽象方法】【也就是说只有方法声明而没有方法的实现那么就是抽象方法】


使用abstract关键字来声明不完整的方法。【abstract public function 方法名();】
一旦有抽象方法的话,那么这个类就是抽象类,也需要abstract关键字进行声明
【抽象类中可以没有抽象方法,但是一旦一个类中有抽象方法,那么该类就一定是抽象类】


抽象类只能被继承【这点是重点】
继承后的类需要对原本的抽象类中的抽象方法进行重写【将不完整方法进行完善】


抽象类的用处就是:
通过抽象类的定义进行规定其子类使用的一致方法的定义【该方法每一个子类都需要进行重写,也就是该方法时子类都必须存在,但是可以各自不同】
【抽象类是考虑到子类都必须出现的方法和接口进行区别,interface类其实是规范化】


【抽象类和final类都是基于业务逻辑层面来定义的特殊类:final类只被实例化对象,abstract类用来限定子类的结构】
【final方法在继承中不能被更改】

【类和方法在final和abstract关键字修饰和正常的情况】
在类的层面上,final和abstract类指代了两种特殊的类
在方法的层面上,final保证了方法在继承中的不可更改,abstract保证了方法在继承子类中的结构确认

通过这两个关键字和普通类和方法的定义实现了父类对继承子类的结构和内容的基本控制

 

4.interface【接口和实现implement】
抽象的方法本身也是一种implement。

接口,指的是对象的公共方法。【接口的方法的属性都是公共方法。抽象方法内属性可以做公共方法也可以使protected】
定义一个结构,用于限制一个类或对象应该具备的公共方法。

【接口决定了实现该接口的类(对象)的一定要具备的方法】


接口中的特殊点:
【接口内定义的接口方法,只能是public方法,另外不会在接口内包含完整的方法】
【接口内只能包含公共的接口方法(接口方法本身就是不完整的方法)】
【接口相当于将抽象类中抽象方法中的public的方法进行单独取出来,放入接口中】【这样保证类实现接口内所定义的所有接口方法】

【而且因为接口的方法都是public方法,所以实现接口的方法只能是public(implements实现该接口方法之后,权限只能比接口方法的权限更宽,只能是public)】
【接口主要是对外使用的,不仅仅是框架中定义的方法,框架中确保继承使用的子类结构使用的还是abstract,但是接口更偏向外】


【接口与抽象类之间的区别】
(1)抽象类与普通类之间是继承关系【可以得到抽象类中的完整成员,然后才需要实现抽象方法】
(2)接口与普通类之间是实现关系【接口中并没有完整成员,只有接口方法,所以实现只能实现接口】
(3)接口只用来定义公共方法,抽象类可以进行定义更多【只要是公共的成员都可以】
使用接口来规定公共操作,使用抽象类来定义公共的内容(包括属性和完整的成员)【将抽象方法使用接口进行实现,将公共内容使用抽象类进行整合】
以上便是二者之间的区别和现实使用中的结合点。

继承只能是单继承【子类只能继承一个父类】
但是实现可以使多实现【一个类可以实现多个接口implements关键字】


接口可以定义常量【这一点要注意:接口常量const关键字】
相当于实现时,每一个实现的子类都包含该常量

【注意点】
(1)接口不是类【所以接口不是抽象类的特例】class_exist()判断【只是接口本身实现了抽象类的外层定义】
(2)php是单继承,如何实现多继承【利用接口的多实现机制来模拟,但是绝对不是继承】

可以理解为类是对象的设计图纸,接口是类的设计图纸【所以接口本身就不是类】
【final、abstract、interface这三个关键字来限制类的设置】

 

5.__autoload

项目中如何管理类?
为每个类独立的创建一个文件,用于保存该类的代码。在使用时,对该文件进行载入即可。
【所以类名和文件对应,通过类名进行文件加载即可。这也就是自动加载机制的使用】

【之前的解决方法是将所有的类全部载入,加载文件太多,这样对编译和处理的过程太过冗余】
【现在解决这个载入问题的方法:就是根据需要,如果该文件没有被载入,那么加载相应文件】

解决方案需要解决的问题:
(1)判断当前类是否已经被加载。
(2)该类在哪个文件中【类名和文件名一致】
(3)如何判断需要这个类【实例化,继承等等都是需要这个类。如何实现判断需要类的时机是自动加载的关键】
【解决方法】
使用php的类文件,自动加载机制来完成。
【当需要一个类,但是并没有找到该类的定义。此时php内部会自动尝试调用__autoload的函数。会将当前需要的类名作为参数传递到auto_load函数中】
正因为有这种机制,我们只需要对类和文件进行对应,并且设置自动检索区域,便能实现对类的检索,检索之后并且进行针对加载。【在__autoload函数进行定义载入文件便能实现自动加载】


实质上我们需要进行解决的就是,对类名和文件名进行一致化(也就是类单独进行创建一个文件),并且对该文件进行加载。
【所以我们需要(命名规则:类名和文件名一致)和(包含文件的方法写入__autoload函数中)这两点便能实现自动加载的功能】


【自动加载这个功能需要注意的就是php的内部机制。因为php能够很好的识别php使用类的时候,只是多对该类进行一次查找和调用__autoload函数】


【公司项目的文件加载机制】
通过include_path设置自动检索区域,对路径进行简单使用,然后对自动加载的方法实现类名加载文件

 

6.序列化和反序列化【串行化与反串行化】serialize unserialize
数据永久化的概念【例如将数据保存在文件内,数据库等】
在保存数据的过程中,数据的格式是一个问题。文件内只能存字符串【而php本身的数据类型有八种,所以需要将php里除了字符串之外的数据类型的数据需要转化为字符串】
这也就是序列化【与json很好区别。json的数据格式是js默认能够接受的数据格式,而不是所谓的字符串】


数据类型:相应的数据结构和定义在该结构上的操作
在传输和存储过程中都是流的形式【字符串】所谓的流?

一旦数据类型不是字符串,就会导致数据不能原始保存或者传输。【这也就是序列化的使用场景】
php所有的数据类型都可以被序列化和反序列化【资源例外。因为资源本身就是对外部的操作,而且外部的操作不能持久化。只有把资源换成其他类型的数据之后,才能被序列化】

【重点】
对象被序列化和反序列化:
(1)将对象序列化保存到一个文件中时,该信息会很好的保存,但是并不会保存对象指定的类,导致了反序列化后,显示的该对象就是__php_incomplete_class类的对象。所以需要在反序列化之前将该类载入,才能正常进行读取反序列化结果
【原因:对象中并不会存方法,所以需要指定该类】
(2)反序列化也会出发自动加载机制【因为需要找到类】【只要使用自动加载函数定义正常,便能正常载入类】
【因为自动加载会自动传入类名,该类名在序列化的结果里有声明】

(3)反序列化之后的对象还需要多注意【尤其是需要使用该对象做处理时】
【例子是数据库连接后的对象,因为资源不能被序列化和反序列化,该数据库连接对象并不能在反序列化之后正常连接数据库】
【所以需要我们在反序列化之后获得的数据之后,再进行一次连接】
【在序列化时可以自定义保存序列化的对象中的属性是否被序列化,在反序列化时可以自动执行某些代码,从而完成】
【__sleep()和__wakeup()方法保证了对象的序列化和反序列之中的处理】


7.__sleep和__wake up
【应用场景就在对象在序列化和反序列化的过程中控制对象属性是否被序列化的方法】
【保证对象在序列化和反序列化过程中也能正常处理资源这样的属性的功能,保证代码的自动化】

__sleep()方法会在对象被序列化时,自动调用,返回一个数组。数组中的每一个元素表示一个属性名。数组内存在的属性名才会被序列化
【这样就能够通过这样的方法进行对象序列化时限制对象中属性是否被序列化】
function __sleep(){
return array(‘希望被序列化的属性‘);//这个函数会被自动调用,所以只需要有这个返回值便能实现对要序列化的属性控制
}

__wakeup()方法在对象对反序列化时,自动调用,实现反序列化之后缺失的一些能力的处理
【例如反序列化之后对象的资源属性的重新初始化】

【总结:魔术方法】
__construct
__destruct
__sleep
__wakeup
这四个方法
php自动调用,用户脚本进行定义,而且在特定情境下才会被调用


8.对象的拷贝与克隆
对象的赋值是按引用传递【两个对象之间进行赋值之后,如果改变一个,那么另一个也起作用】
保存对象的变量内,保存的是对象的标识,而不是变量本身。所以使用两个对象的变量进行赋值的过程中,只是将该变量指向对象的标识复制了一份,而对象的标识和对象之间的引用关系并未变化
【这就是说对象的变量的只能是指向该标识】
【所以对象的变量的改变,都是使用该对象标识进行对象值的改变,所以看来对象时按引用的效果】


但是有时候我们需要对象的整体复制【克隆clone关键字】
【克隆需要注意的就是__clone()这样的魔术方法】
但是克隆并不会完全一样,因为这两份数据也需要进行区别。
在克隆是调用__clone()方法来对克隆操作之后添加一些识别的属性。【这个方法也是自动调用,在__clone()方法内的$this指代的是克隆后的新方法】
【我们在编程中也要对克隆后的新对象增加额外的识别属性】

 

 

【数组的拷贝相关知识回顾,另外foreach】


【问题】
数据的流的显示

访问修饰限定符的简单总结、final/abstruct/interface对类的限制、自动加载机制、序列化与反序列化【数据持久化和对象的序列化问题】、对象的拷贝(按引用是因为对象标识)和克隆(__clone方法中的this指向)