1.什么是面向对象?
面向对象编程(Object Oriented Programming, OOP, 面向对象程序设计)是一种计算机编程架构,
OOP的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成
OOP达到了软件工程的三 个目标:重用性、灵活性和扩展性。
为了实现整体运算,每个对象都能够接收信息、处理数据和向其它对象发送信息。
OOPD的好处:首先,面向对象符合人类看待事物的一般规律。其次,采用面向对象方法可以使系统各部分各司其职、各尽所能。为编程人员敞开了一扇大门,使其编程的代码 更简洁、更易于维护,并且具有更强的可重用性。
2.什么是类,什么是对象,类和对象这间的关系
类的概念:类是具有相同属性和服务的一组对象的集合。它为属于该类的所有对象提供了统一的抽象描述,其内部包括属性和服务两个主要部分。
对象的概念:对象是系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位。客观世界是由对象和对象之间的联系组成的
类与对象的关系就如模具和铸件的关系,类的实例化结果就是对象,而对一类对象的抽象就是类,类描述了一组有相同特性(属性)和相同行为(方法)的对象。
3.什么是面向对象编程呢?
举例说明: 就不说他的概念,如果你想建立一个电脑教室,首先要有一个房间, 房间里面要有N台电脑,有N个桌子, N个椅子, 白板, 投影机等等,这些是什么,刚才咱们说了, 这就是对象,能看到的一个个的实体,可以说这个电脑教室的单位就是这一个个的实体对象, 它们共同组成了这个电脑教室,那么我们是做程序,这和面向对象有什么关系呢?
开发一个系统程序和建一个电脑教室类似,你把每个独立的功能模块抽象成类并形成对象,由多个对象组成这个系统,这些对象之间都能够接收信息、处理数据和向其它对象发送信息等等相互作用。就构成了面向对象的程序。
4.如何抽象出一个类?
上面已经介绍过了, 面向对象程序的单位就是对象,但对象又是通过类的实例化出来的,所以我们首先要做的就是如何来声明类,
1 |
class 类名{ |
2 |
} |
比如说,一个人就是一个对象,你怎么把一个你看好 的人推荐给你们领导呢?当然是越详细越好了:
首先, 你会介绍这个人姓名、性别、年龄、身高、体重、电话、家庭住址等等。
然后,你要介绍这个人能做什么, 可以开车, 会说英语, 可以使用电脑等等。
只要你介绍多一点, 别人对这个人就多一点了解, 这就是我们对一个人的描述,
从上面人的描述可以看到, 做出一个类来, 从定义的角度分两部分, 第一是从静态上描述, 第二是从动态上描述, 静态上的描述就是我们所说的属性, 像上面我们看到的,人的姓名、性别、年龄、身高、体重、电话、家庭住址等等。 动态上也就是人的这个对象的功能,比如这个人可以开车, 会说英语, 可以使用电脑等等,抽象成程序时,我们把动态的写成函数或者说是方法,函数和方法是一样的。所以,所有类都是从属性和方法这两方面去写, 属性又叫做这个类的成员属性,方法叫做这个类的成员方法。
class Person { //下面是人的成员属性
var $name; //人的名子
var $sex; //人的性别
var $age; //人的年龄
//下面是人的成员方法
function say() { //这个人可以说话的方法
echo "这个人在说话";
}
function run() { //这个人可以走路的方法
echo "这个人在走路"; } } ?>
|
|
5.如何实例化对象?
当定义好类后,我们使用new关键字来生成一个对象。
$对象名称 = new 类名称();
6.如何去使用对象中的成员
对象->属性 $p1->name; $p2->age; $p3->sex;
对象->方法 $p1->say(); $p2->run(); 如下面实例:
classPerson
{
//下面是人的成员属性
var $name; // 人的名子
var $sex; // 人的性别
var $age; // 人的年龄
//下面是人的成员方法
function say() { // 这个人可以说话的方法
echo "这个人在说话";
}
function run() { //这个人可以走路的方法
echo "这个人在走路";
}
}
$p1 = newPerson(); //创建实例对象$p1
$p2 = newPerson(); //创建实例对象$p2
$p3 = newPerson(); //创建实例对象$p3
//下面三行是给$p1对象属性赋值
$p1->name= "张三";
$p1->sex= "男";
$p1->age= 20;
//下面三行是访问$p1对象的属性
echo"p1对象的名子是:" . $p1->name;
echo"p1对象的性别是:" . $p1->sex;
echo"p1对象的年龄是:" . $p1->age;
//下面两行访问$p1对象中的方法
$p1->say();
$p1->run();
//下面三行是给$p2对象属性赋值
$p2->name= "李四";
$p2->sex= "女";
$p2->age= 30;
//下面三行是访问$p2对象的属性
echo"p2对象的名子是:" . $p2->name;
echo"p2对象的性别是:" . $p2->sex;
echo"p2对象的年龄是:" . $p2->age;
//下面两行访问$p2对象中的方法
$p2->say();
$p2->run();
//下面三行是给$p3对象属性赋值
$p3->name="王五";
$p3->sex="男";
$p3->age=40;
//下面三行是访问$p3对象的属性
echo"p3对象的名子是:" . $p3->name;
echo"p3对象的性别是:" . $p3->sex;
echo"p3对象的年龄是:" . $p3->age;
//下面两行访问$p3对象中的方法
$p3->say();
$p3->run();
?>
7.特殊的引用“$this“的使用
$this就是对象内部代表这个对象的引用
8.构造方法__construct()与析构方法__destruct()
9.封装性(var与public,protected,private的关系)
封装性是面象对象编程中的三大特性之一,封装性就是把对象的属性和服务结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节,
1. 把对象的全部属性和全部服务结合在一起,形成一个不可分割的独立单位(即对象)。
2. 信息隐蔽,即尽可能隐蔽对象的内部细节,对外形成一个边界〔或者说形成一道屏障〕,只保留有限的对外接口使之与外部发生联系。
封装的原则在软件上的反映是:要求使对象以外的部分不能随意存取对象的内部数据(属性),从而有效的避免了外部错误对它的"交叉感染",使软件错误能够局部化,大大减少查错和排错的难度。
用个实例来说明吧, 假如某个人的对象中有年龄和工资等属性,像这样个人隐私的属性是不想让其它人随意就能获得到的,如果你不使用封装,那么别人想知道就能得到,但是如果你封装上之后别人就没有办法获得封装的属性, 除非你自己把它说出去,否则别人没有办法得到。
10.__set(),__get(),__isset(),__unset()四个方法的应用
一般来说,总是把类的属性定义为private,这更符合现实的逻辑。但是, 对属性的读取和赋值操作是非常频繁的,因此在PHP5中,预定义了两个函数”__get()”和”__set()”来获取和赋值其属性,以及检查属性的”__isset()”和删除属性的方法”__unset()”。
//__get()方法用来获取私有属性
function __get($property_name) {
if (isset($this->$property_name)) {
return($this->$property_name);
} else {
return(NULL);
}
}
//__set()方法用来设置私有属性
function __set($property_name, $value) {
$this->$property_name = $value;
}
我们来看一个完整的实例:
class Person{
//下面是人的成员属性
private$name; //人的名子
private$sex; //人的性别
private$age; //人的年龄
//__get()方法用来获取私有属性
privatefunction __get($property_name) {
if(isset($this->$property_name)) {
return($this->$property_name);
} else { return NULL ; } }
//__set()方法用来设置私有属性
privatefunction __set($property_name, $value) {
$this->$property_name = $value;
}
//__isset()方法
private function __isset($nm) {
echo "isset()函数测定私有成员时,自动调用
";
return isset($this->$nm);
}
//__unset()方法
private function __unset($nm) {
echo "当在类外部使用unset()函数来删除私有成员时自动调 用的
";
unset($this->$nm);
}
}
$p1 = new Person();
$p1->name = "this is a personname";
//在使用isset()函数测定私有成员时,自动调用__isset()方法帮我们完成,返回结果为true
echo var_dump(isset($p1->name)) ."
";
echo $p1->name . "
";
//在使用unset()函数删除私有成员时,自动调用__unset()方法帮我们完成,删除name私有属性
unset($p1->name);
//已经被删除了,所这行不会有输出
echo$p1->name;
?>
11.类的继承
继承作为面向对象的三个重要特性的一个方面,在面向对象的领域有着及其重要的作用
继承是PHP5面象对象程序设计的重要特性之一,
说的简单点就是,继承性是子类自动共享父类数据结构和方法的机制,这是类之间的一种关系
在PHP和Java语言里面没有多继承,只有单继承,也就是说,一个类只能直接从一个类中继承数据,这就是我们所说的单继承。
//定义一个“人”类做为父类
class Person{
//下面是人的成员属性
var $name; //人的名子
var $sex; //人的性别
var $age; //人的年龄
//定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值
function__construct($name, $sex, $age) {
$this->name = $name;
$this->sex = $sex;
$this->age = $age;
}
//这个人可以说话的方法, 说出自己的属性
function say(){
echo"我的名子叫:" . $this->name . " 性别:" . $this->sex . " 我的年龄是:". $this->age;
}
定义一个子类“学生类“使用”extends”关键字来继承”人”类:
class Studentextends Person
{
var $school; //学生所在学校的属性
//这个学生学习的方法
function study() {
echo "我的名字叫:" . $this->name . " 我正在" .$this->school . "学习
";
}
}
12.重载新的方法(parent::)
PHP中的方法是不能重载的, 所谓的方法重载就是定义相同的方法名,通过“参数的个数“不同或“参数的类型“不 同,来访问我们的相同方法名的不同方法。
不能重载的原因:
但是因为PHP是弱类型的语言, 所以在方法的参数中本身就可以接收不同类型的数据,又因为PHP的方法可以接收不定个数的参数,所以通过传递不同个数的参数调用不相同方法名的不同方法也是不成立的。所以在PHP里面没有方法重载。
通过两种方法实现在子类的方法中调用父类被覆盖的方法:
一种是使用父类的“类名::“来调用父类中被覆盖的方法;
一种是使用“parent::”的方试来调用父类中被覆盖的方法;
应该用特殊的名字 parent,
13.访问类型(public,protected,private)
public (公有的、默认的),protected(受保护的)和private (私有的)三种。
14.final关键字的应用
这个关键字只能用来定义类和定义方法, 不能使用final这个关键字来定义成员属性,因为final是常量的意思,我们在PHP里定义常量使用的是define()函数,所以不能使用final来定义成员属性。
使用final关键标记的类不能被继承;
使用final关键标记的方法不能被子类覆盖,是最终版本;
15.static和const关键字的使用
static关键字是在类中描述成员属性和成员方法是静态的;
static成员能够限制外部的访问,因为static的成员是属于类的,是不属于任何对象实例,是在类第一次被加载的时候分配的空间,其他类是无法访问的,只对类的实
static关键字是在类中描述成员属性和成员方法是静态的;静态的成 员好处在哪里呢?前面我们声明了“Person”的人类,在“Person”这个类里如果我们加上一个“人所属国家”的属性,这样用“Person”这个 类实例化出几百个或者更多个实例对象,每个对象里面就都有“所属国家”的属性了,如果开发的项目就是为中国人而开发的,那么每个对象里面就都有一个国家的属性是 “中国“其它的属性是不同的,如果我们把“国家”的属性做成静态的成员,这样国家的属性在内存中就只有一个,而让这几百个或更多的对象共用这一个属性,static成员能够限制外部的访问,因为static的成员是属于类的,是不属于任何对象实例,是在类第一次被加载的时候分配的空间,其他类是无法访问的,只对类的实例共享,能一定程度对类该成员形成保护;
从内存的角度我们来分析一下,内存从逻辑上被分为四段,其中对象是放在“堆内存”里面,对象的引用被放到了“栈内存“里,而静态成员则放到了“初始化静态段”,在类第一次被加载的时候放入的,可以让堆内存里面的每个对象所共享,如下图:
类的静态变量,非常类似全局变量,能够被所有类的实例共享,类的静态方法也是一样的,类似于全局函数。
const是一个定义常量的关键字,在PHP中定义常量使用的是“define()”这个函数,但是在类里面定义常量使用的是“const”这个关键字
17.克隆对象__clone()方法
18.__call()处理调用错误
19.抽象方法和抽象类(abstract)
在OOP语言中,一个类可以有一个或多个子类,而每个类都有至少一个公有方法做为外部代码访问其的接口。而抽象方法就是为了方便继承而引入的,我们先来看一下抽象类和抽象方法的定义再说明它的用途。
什么是抽象方法?我们在类里面定义的没有方法体的方法就是抽象方法,
例如:
1 |
abstractfunctionfun1(); |
2 |
abstractfunctionfun2(); |
那么什么是抽象类呢?只要一个类里面有一个方法是抽象方法,那么这个类就要定义为抽象类,抽象类也要使用“abstract”关键字来修饰;在抽象类里面可以有不是抽象的方法和成员属性,但只要有一个方法是抽象的方法,这个类就必须声明为抽象类,使用”abstract”来修饰。
子类必须把父类中的抽象方法全部都实现,否则子类中还存在抽象方法,那么子类还是抽象类,还是不能实例化类
20.PHP5接口技术(interface)
PHP与大多数面向对象编程语言一样,不支持多重继承。也就是说每个类只能继承一个父类。为了解决这个问题,PHP引入了接口,
接口的思想是指定了一个实现了该接口的类必须实现的一系列方法。接口是一种特殊的抽象类,抽象类又是一种特殊的类,所以接口也是一种特殊的类
为 什么说接口是一种特殊的抽象类呢?如果一个抽象类里面的所有的方法都是抽象方法,那么我们就换一种声明方法使用“接口”;也就是说接口里面所有的方法必须 都是声明为抽象方法,另外接口里面不能声明变量(但可声明常量constant),而且接口里面所有的成员都是public权限的。所以子类在实现的时候 也一定要使用public权限实限。
我们可以使用”extends”关键字让一个接口去继承另一个接口:
而我们定义一接口的子类去实现接口中全部抽象方法使用的关键字是“implements”,而不是我们前面所说的“extends”;
21.多态的应用
多态是除封装和继承之外的另一个面象对象的三大特性之一
我个人看来PHP中虽然可以实现多态,但和c++还有Java这些面向对象的语言相比,多 态性并不是那么突出,因为PHP本身就是一种弱类型的语言,不存在父类对象转化为子类对象或者是子类对象转化为父类对象的问题,所以多态的应用并不是那么的明显;
所谓多态性是指一段程序能够处理多种类型对象的能力,比如说在公司上班,每个月财务发放工资,同一个发工资的方法,在公司内不同的员工或是不同职位的员工,都是通过这个方法发放的,但是所发的工资都是不相同的。所以同一个发工资的方法就出现了多种形态。
对于面向对象的程序来说,多态就是把子类对象赋值给父类引用,然后调用父类的方法,去执行子类覆盖父类的那个方法,但在PHP里是弱类型的,对象引用都是一样的不分父类引用,还是子类引用。
22.把对象串行化serialize()方法,__sleep()方法,__wakeup()方法
有时候需要把一个对象在网络上传输,为了方便传输,可以把整个对象转化为二进制串,等到达另一端时,再还原为原来的对象,这个过程称之为串行化(也叫序列化),
23.自动加载类 __autoload()函数
很多开发者写面向对象的应用程序时,对每个类的定义建立一个 PHP 源文件。一个很大的烦恼是不得不在每个脚本(每个类一个文件)开头写一个长长的包含文件的列表。
在 PHP 5 中,可以定义一个 __autoload()函数,它会在试图使用尚未被定义的类时自动调用,通过调用此函数,
你做项目时,在组织定义类的文件名时,需要按照一定的规则,最好以类名为中心,也可以加上统一的前缀或后缀形成文件名,比如 xxx_classname.php、classname_xxx.php以及就是classname.php等等。