面向对象

类是得到对象的一种方法,所以想要得到对象必须先有类。

对象、属性、方法

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 会给该喊出传递一个参数,当前需要的类的类名。(所以强调类名的一致性,通过类名能找到类文件)

注册其他的自动加载函数#

  1. 定义一个可以加载类文件的普通函数#

  2. 将该普通的函数注册成自动加载函数#

    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 中一共三个访问范围:

  1. 当前类内
  2. 继承连类内
  3. 类外
public:公开的,当前类内,继承链类内以及类外都可以访问
protected:受保护的,当前类内,继承链类内可以访问
private:私有的,只有当前类内可以访问

访问控制修饰符:public private protected

注意点:

子类重写父类的成员的时候,子类的访问控制符的作用范围不低于父类

父类 public 子类 只能是 public

父类 protected 子类是 public protected

final 最终类和 abstract 抽象类#

类的两个功能

  1. 被继承
  2. 实例化对象

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 重载简介#

指的是对不可访问的成员的处理,称之为成员的重载!

  1. 成员不存在
  2. 成员声明成了 private、protected,无权限

也就是说,为一个不存在的属性赋值的时候,PHP 默认是支持将该属性重新载入到当前对象内部的!这种现象就称之为属性的重载!

属性重载#

  1. 为不可访问的属性赋值的时候:__set ()
  2. 获取不可访问的属性的时候:__get()
  3. 删除不可访问的属性的时候:__unset ()
  4. 判断不可访问的属性是否存在的时候:__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 的三个功能

  1. 函数中的静态属性
  2. 当前类
  3. 定义类中的静态成员

总结:目前代表类的关键字有几个?

== 一共有三个:==

self:当前类,绑定(确定)类名的时机发生在代码的预编译阶段

static:当前类,绑定(确定)类名的时机发生在代码的执行阶段

parent:父类

单例模式#

只需要实例化出来一个对象就可以完成所有的功能!一个典型的类就是数据库工具类!所以,如果我们能够通过某些技巧,使得 == 一个类只能开辟一个对象 == 空间的话,就可以节省相应的对象资源,这种模式就叫作单例模式!

  1. 防止用户通过 new 关键字无限实例化对象 (== 构造方法私有化 ==)
  2. 增加一个静态的公共方法,进入到类的内部 (静态方法:还没有对象,用类访问,公共方法,类外调用) (如何防止用户无限调用,判断当前静态属性里保存的是不是由当前类实例化而来的,如果不是,才返回对象)
  3. 为当前类增加一个私有的静态属性 (类来访问,类外无法修改属性的值)
  4. 私有化克隆方法 (防止克隆)

工厂模式#

:设计一个类(此时这个类就叫作工厂类),该类的作用就是帮助其他的类 “生产” 对象(实例化对象),也就是说,== 只要传递给这个 “工厂” 一个类名,就可以得到一个相应的对象!==

约束类型#

形参约束为 $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 协议》,转载必须注明作者和本文链接