如果你是一个早期从php4走过来的programmer同时你又没有学习过其他面形对象语言,可能你会对面向对象这个概念模糊。
我们先从面相对象的组成和初级的使用方法来解开面相对象神秘的面纱。
书中对面向对象的描述是这样的:
- 面向对象编程(OOP)是一种计算机编程架构。而它的特点:重用性、灵活性和扩展性。具体表现形式说白了就是,类,对象。
这里有一个问题:类与对象之间的关系?
- 一句话概括,类的实例化结果就是对象,而对象的抽象就是类。
那什么是类呢?
- 类是一个独立的程序单位,具有相同属性和服务的一组对象的集合。
什么又是对象?
- 在客观世界里,所有事物都是有对象和对象之间的联系组成的。
(以上内容比较抽象,可以看书中例子)
下面我们直接来说面向对象的用法。
使用面向对象我们就需要创建一个类,现在我们来说一下一个类的基本组成部分:
修饰符 class 类名{
修饰符 成员属性
修饰符 成员方法
}
修饰符分别在类、成员属性、成员方法中使用:
- abstract 抽象声明
- final 类不被继承
- static 静态声明
- const 定义类中属性为常量
- public 全局声明
- private 私有的
- protected 受保护的
成员属性:在类中声明的变量就是成员属性,一个类可以声明多个变量来存储不用属性的信息。
成员方法:在类中创建的函数就称为成员方法,一个类可以声明多个函数。
如果你想使用这个类,必须把它实例化成对象,使用new关键字后面加上类的名字就可以了
$变量名 = new 类名称
如何使用类中的成员属性和成员方法呢?它需要一个符号来完成"->"
$引用名 = new 类名称
$引用名 -> 成员属性
当然也可以赋值
$引用名 -> 成员属性=赋值
访问成员方法
$引用名 -> 成员方法
具体用法还是多多实际操作。
如果类里面的引用如何办到呢?
- "$this"在类内部中使用它便可以在类内部实现引用啦。
说了这么多面向对象知识,当然不能忘记面向对象三大特性,封装、继承、多态,逐个说明。
封装:封装就是把类中的成员属性和成员方法结合成一个独立的单位,并尽可能隐藏类的内部细节。
由此可见封装解决了一部分的安全问题。既然封装是把类作为一个独立的单位,如何防止实例化时调用类中的成员属性和成员方法?答案就是使用修饰符,我们上面讲过:
- public 全局声明:成员没有访问限制
- private 私有的:当前类里面成员没有访问限制,子类或外部不行
- protected 受保护的:当前类以及子类没有访问限制,外部不行
( 这三个是作为类中的权限修饰符 )
在成员属性和成员方法之前声明他们就具备了相同的特性,从而达到外部无法访问的目的。
php提供了很多魔术方法,在封装的使用上面也体现到了,这个我们下面一起讲,现在我们继续说面向对象的另一个特性,继承。
继承:建立一个基类,从父类中继承数据和成员属性、成员方法,说简单点继承就是子类对父类进行功能扩展。
它使用了一个关键字来实现继承:extends:
class 基类 extends 父类名 { ... }
有人说php中的面向对象是“伪面向对象”,我不太认同此类说法,的确相比于其他强类型语言,php对面向对象的支持由于它本身的语言结构无法做到完善。但就面向对象而言php是完全可以的。
在实际开发中,尤其是多人多模块开发环境,有很多核心的类是不需要被外界使用的,也就是说它不能被继承,php提供了一个关键字来实现:final:
final class 类名称{}
在声明一个类之前加入这个关键字,此时的类将不被继承。
static 关键字
可以将类中成员属性和成员方法标注为静态。
而在类里面的成员方法里使用静态的成员属性不能使用this了,php提供了一个“self”,它的使用方法和this有所不同:
class 类{
static $变量;
public function 方法(){
#想要使用静态变量
self::$变量
}
}
也可以在实例化类之后访问静态方法;
class 类{
static function 方法(){...}
}
#在实例化之后也可以如此使用
$实例化 = new 类();
$实例化::静态方法();
这里可以自行实践一下,留一个问题:静态变量再次赋值时,原有值不会被改变,那么,静态变量在内存中时如何存储的呢?他又是如何被销毁呢?
php还有 const 关键字:用来将类中的成员属性定义为常量。
由于对象模型是通过引用来调用对象,但我们有时候需要建立一个副本,改变对象时不希望影响到副本。php使用 clone 克隆来实现。
说一下常用的魔术方法:
- 构造函数 __construct
- 析构函数 __destruct
构造函数是对象创建完成后第一个被对象自动调用的方法。
析构函数是销毁前最后一个被对象自动调用的方法。
( 这两个有关对象的生命周期,了解之后对他们使用就不陌生了 。这里有必要简单说明一下php的垃圾回收机制,在对象不能被访问时会自动启动,回收资源。)
下面这组针对面向对象封装来操作成员属性的。
- 获取私有属性 __get
- 设置私有属性 __set
- 判断私有属性是否被设置 __isset
- 删除私有属性 __unset
其中 __isset和__unset 与函数 isset 和 unset用法相同。
还有两个:
- 快速获取对象的字符串 __toString
- 调用对象中不存在的方法时使用 __call
抽象和接口
抽象和接口用法很相似,他们俩属于比较特殊的类。抽象类是一种特殊的类,而接口是一种特殊的抽象类。
说抽象类之前先明白抽象方法的概念:抽象方法是指没有具体工作的方法,它的声明不用花括号,直接以分号结尾,别忘了关键字声明。
abstract function 抽象方法();
( 在类中只要有一个抽象方法,该类就是抽象类 )
接口是一个特殊的抽象类,接口的类必须都是抽象方法,且不可以有变量只能使用 const 关键字声明常量,所有成员必须是 public 公共的
抽象类和接口都可以被继承,接口的继承使用的是 implements。
面向对象第三个特性:多态。
多态:所谓多态是指一段程序能够处理多种类型对象的能力。php中多态性就是重写。
实现多态主要就是 抽象类 和接口。在实际开发中我们不管是多人开发环境,还是对接其他语言,都需要有一个规范,而抽象的概念就可以解决这一类的问题。
本书中面向对象单元还有两个知识点,类的自动加载,序列化。
序列化不用多说,就是将对象转换二进制可以支持永久保存,或传输。
类的自动加载 __autoload 这个我准备以后在分析框架时候详细讲解。