面向对象
类是得到对象的一种方法,所以想要得到对象必须先有类。
对象、属性、方法
class Student{
}
类里面应该有属性、方法、类常量。
类常量public $num
;
类常量可以有非计算的默认值
方法可以不写public,是默认。
类的实例化
利用类得到对象的过程就是类的实例化
$student = new Student;
$name = $student->name;
instanceof
判断某个对象是否由某个类实力化而来
$stu instanceof Student
$this关键字
当前类的当前对象
为什么打印对象的时候只有属性被打印出来
属性归具体的对象管理
方法由类进行管理
构造方法
在new一个对象的同时,自动的调用初始化属性的方法,在实例化一个对象的时候,PHP会自动的调用一个名字叫作__construct()的方法
析构方法
析构方法是在一个对象“销毁”(消失)的时候由系统自动调用!
析构方法的名字为:__destruct(),注意该方法里面不能有任何的参数!
作用不是为了删除一个对象,而是为了释放该对象所占用的额外资源
析构方法在对象消失之前调用
对象的传值与克隆
对象的变量名引用的是对象的内部编号,值传递的时候,只是赋值这个内部编号。没有开启一个新的对象空间,所以说是"浅复制"。
对象的克隆
赋值无法获取新的对象,只有通过克隆,通过一个对象得到一个新的对象
新对象 = clone 已有的对象
克隆不是实例化,不能触发构造方法,为了与旧对象做区分,用到__clone()
,克隆的时候自动调用此方法。
静态属性
class Student{
public static $stu_num = 0;
}
属于所有的对象共有的成员,类来管理
public \ protected \private static 属性名
静态属性的访问
类名:静态属性名,Student::$stu_age
;,因为归类管理,不属于某个对象,所以无法使用对象直接访问静态属性。类的内部可以使用self。
静态方法
所有对象共享的方法,类来管理,public static function showNum(){}
,不能使用$this这个方法,因为static静态方法本来就是公共的方法.
$this关键字本身就体现了各个对象。类调用静态属性,对象调用非静态属性
self、static、$this的区别?
类常量
类中的一个常量,const CLASS_ID='610'
类管理,Student::CLASS_ID
类中的成员
静态属性
非静态属性
静态方法
非静态方法
类常量
类空间:静态属性、类常量
对象空间:非静态属性
用户代码区:非静态方法、静态方法
自动加载机制
-
按需
-
自动
PHP在执行的时候,发现需要一个类,当前脚本没有,会调用
__autoload
会给该喊出传递一个参数,当前需要的类的类名。(所以强调类名的一致性,通过类名能找到类文件)
注册其他的自动加载函数
-
定义一个可以加载类文件的普通函数
-
将该普通的函数注册成自动加载函数
spl_autoload_register(函数名);
注意:
- 函数的注册一定要发生在需要某个类之前
- 一旦注册了其他的自动加载函数,那么系统默认的__autoload()函数就失效了!如果想继续使用,必须像注册其他普通函数一样,重新的进行注册!
注册非静态方法
首先,要实例化一个对象出来
其次,spl_autoload_register函数的参数为一个索引数组,该数组里面只有两个元素,第一个元素为一个对象变量,第二个元素为方法名!
注册静态方法
此时,spl_autoload_register函数的参数为一个索引数组,该数组里面只有两个元素,第一个元素为一个类名,第二个元素为方法名!
数据的序列化和反序列化
为什么需要序列化和反序列化
因为文件中只能保存字符串,当写入的内容是false,取到的时候会是空字符串。这样就没有保障数据的原样输出。
序列化 serialize()
反序列化unserialize()
不能序列化资源类型,因为是外部数据,在变化的,也没有意思保存。其中,session和cookie的区别,在于session能保存除了资源类型外的所有类型,cookie只能保存字符串,就因为session有序列化和反序列化。
__sleep()
序列化的时候,存在不想被序列化的数据(资源类型),用到__sleep()
序列化一个对象的时候由系统自动调用!
作用:该方法用于规定哪些属性应该被序列化,实现的方式为:返回一个索引数组,数组内的元素为需要被序列化的属性名的集合!
__wakeup
触发时机:在反序列化一个对象的时候自动触发!
作用:就是在反序列化一个对象的时候,对该对象进行一系列的初始化操作!
类的三大特性
封装性、继承性、多态性
子类实例化出来的对象也同时是其父类的一个实例
几个概念
继承:一个类从另一个已有的类获得其成员和特性,就是继承!
派生:从一个已有的类产生一个新的类,叫作派生!
注意:继承和派生其实是从不同的方向来描述的一个概念,本质上是一样的!
父类:也叫作基类,就是指以后的那个被继承的类
子类:也叫作派生类或扩展类
扩展:在子类中增加一些自己特有的特征信息(属性、方法和类常量),没有扩展,继承也就没有任何的意义!
单继承:==一个类只能继承自一个其他的类==,不能继承多个类,单继承也是大多数面向对象的语言的特性(C++就是多继承)
重写override
重写也叫作覆盖,就是指当子类成员和父类成员名字相同的时候,从父类继承下来的成员就会重新定义!
代码描述
class A,classB分别都有function C (输出当前类的属性)
class B 继承 classA
实例化B,重新赋值,
调用function c 会输出class B的属性
重写机制是由继承链来决定的,子类找到了就不会再在父类中找
如果要强制性执行父类的同名方法,需要显式调用 父类名::父类方法名
Parent关键字
相对于self代表的当前所属类的类名,parent关键字代表的是其父类的名字!通常用于在子类中调用父类的成员的时候使用!
可能是父类,也可能是父类的父类
访问控制修饰符
PHP中一共三个访问范围:
- 当前类内
- 继承连类内
- 类外
public:公开的,当前类内,继承链类内以及类外都可以访问
protected:受保护的,当前类内,继承链类内可以访问
private:私有的,只有当前类内可以访问
访问控制修饰符:public private protected
注意点:
子类重写父类的成员的时候,子类的访问控制符的作用范围不低于父类
父类 public 子类 只能是public
父类 protected 子类是 public protected
final最终类和abstract抽象类
类的两个功能
- 被继承
- 实例化对象
final类:最终类,不能被继承,只能实例化对象
abstract类:抽象类,不能实例化,只能被继承
抽象类,不同的对象实现相同的动作的时候有多种形态(方法)!我们可以在类中规定一些必须要完成的动作(方法),但是不去完善方法体(因为不同的对象实现这个动作的方式不一样),这种方法就叫作抽象方法(不完整的方法)
简单说,抽象类就是包含了抽象方法的类,
abstract class Animal{
publilc function move();
}
继承抽象方法的子类,要么继续做抽象类,要么实现父类中所有的抽象方法。==面向对象的多态性==
interface接口
接口就是一个对象对外的公共的操作方法!规定该接口的下级类必须要实现的公共的方法!
接口常量:其实就是普通的常量,只不过是出现在接口里面而已!
抽象方法:必须声明为public,不需要有abstract关键字
一般来说,接口的名字以大写字母I开头!接口不是类!只是类的一种规范!
接口的实现
class Person implements I_animal{
public function move();
const PI =3.14;
}
接口与抽象类的比较
1, 从逻辑上看,==接口可以看成是抽象类的一个“子集”,接口比抽象类更“抽象”,都可以规定下级类的内部结构,只是接口中只能有公开的抽象方法和接口常量==
2, 接口不是类,而只是类的一种规范,类又是对象的一种规范,但是抽象类是类!
3, PHP不支持多继承,但是支持多实现,也就是说,==一个类可以同时实现多个接口!这也是接口与抽象类的最本质的区别!注意:当一个类实现多个接口的时候,要么实现所有接口中的所有的抽象方法,要么就只能做抽象类!==
overload重载简介
指的是对不可访问的成员的处理,称之为成员的重载!
- 成员不存在
- 成员声明成了private、protected,无权限
也就是说,为一个不存在的属性赋值的时候,PHP默认是支持将该属性重新载入到当前对象内部的!这种现象就称之为属性的重载!
属性重载
- 为不可访问的属性赋值的时候:__set()
- 获取不可访问的属性的时候:__get()
- 删除不可访问的属性的时候:__unset()
- 判断不可访问的属性是否存在的时候:__isset()
方法重载
处理不可访问的方法!
利用两个魔术方法来完成:
__call():当调用一个不可访问的对象方法(非静态方法)的时候,会自动的执行该魔术方法!
__callstatic():当调用一个不可访问的静态方法,会自动的执行该访问,需要在方法的前面加上static
魔术方法和魔术常量
魔术方法
名字由系统定义,而方法体由用户定义的方法!
最大的特点是:不需要用户手动调用,而是当特点的情况方法的时候,系统会自动的调用!
总结,目前,一共学习了哪些魔术方法:
__construct()
__destruct()
__clone()
__sleep()
__wakeup()
__set()
__get()
__unset()
__isset()
__call()
__callstatic()
__invoke()
当把对象当成一个函数(或方法)来使用的时候,会自动的调用该魔术方法,目前使用的不是很多!
__toString()
触发条件:将对象当成是一个字符串来使用的时候,会自动的触发该魔术方法,该方法的返回值,一般就是对象转换为字符串的结果!
面试题
1,$this是不是永远代表当前代码所在类直接实例化出来的对象?
不是!$this的值是根据执行环境来决定,有可能向上或者向下传递!
2,==self是不是永远代表当前代码所在的类==?
是
于是需要static,来完成,当前类,而不是self所在的类。
static的三个功能
- 函数中的静态属性
- 当前类
- 定义类中的静态成员
总结:目前代表类的关键字有几个?
==一共有三个:==
self:当前类,绑定(确定)类名的时机发生在代码的预编译阶段
static:当前类,绑定(确定)类名的时机发生在代码的执行阶段
parent:父类
单例模式
只需要实例化出来一个对象就可以完成所有的功能!一个典型的类就是数据库工具类!所以,如果我们能够通过某些技巧,使得==一个类只能开辟一个对象==空间的话,就可以节省相应的对象资源,这种模式就叫作单例模式!
- 防止用户通过new关键字无限实例化对象(==构造方法私有化==)
- 增加一个静态的公共方法,进入到类的内部(静态方法:还没有对象,用类访问,公共方法,类外调用) (如何防止用户无限调用,判断当前静态属性里保存的是不是由当前类实例化而来的,如果不是,才返回对象)
- 为当前类增加一个私有的静态属性(类来访问,类外无法修改属性的值)
- 私有化克隆方法(防止克隆)
工厂模式
:设计一个类(此时这个类就叫作工厂类),该类的作用就是帮助其他的类“生产”对象(实例化对象),也就是说,==只要传递给这个“工厂”一个类名,就可以得到一个相应的对象!==
约束类型
形参约束为$int,$array,$obj
类和对象的相关函数
class_exists()
类是否存在
interface_exists()
接口是否存在
method_exists()
方法是否存在
get_class()
获得对象所属的类!
get_parent_class()
获得对象的父类!
get_class_methods()
获得一个类的所有的方法名,返回一个数组!需要一个参数是类名!
get_class_vars()
获得一个类的所有的属性!
is_object()
命名空间
电脑中相同文件名的文件,需要文件夹放到不同的空间,同理,代码中相同方法、属性,需要空间划分开。
namespace 空间名字;
子空间
目录:A/B/C,其中C就是B目录的子目录,而B又是A目录的子目录
空间:namespace A\B\C,其中C空间就是B空间的子空间,而B空间又是A空间的子空间(注意使用反斜杠\),其表示的含义是,创建了一个名字为C的子空间,同时A和B空间也一起创建了!
本作品采用《CC 协议》,转载必须注明作者和本文链接