关于PHP面向对象的一点网摘(基本概念与封装性)
本文大部门摘自网络,作为我学习的一点总结也还不错
PHP面向对象技术
本部分一共包括以下一些技术点: 1.面向对象的概念 2.什么是类,什么是对象,类和对象这间的关系 3.什么是面向对象编程呢? 4.如何抽象出一个类? 5.如何实例化对象? 6.如何去使用对象中的成员? 7.特殊的引用“$this”的使用 8.构造方法与析构方法 9.封装性
10.__set()、 __get()、 __isset()、 __unset()四个方法的应用 11.类的继承 12.多态的应用 13.重载新的方法 14.访问类型 15.静态成员的使用 16.final关键字的应用 17.__toString()方法 18.克隆对象 19.__call处理调用错误 20.自动加载类 21.把对象串行化 22.抽象方法和抽象类 23.php5接口技术
1.面向对象的概念 面向对象编程(Object Oriented Programming, OOP, 面向对象程序设计)是一种计算机编程架构,OOP的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成,OOP达到了软件工程的三个目标:重用性、灵活性和扩展性。为了实现整体运算,每个对象都能够接收信息、处理数据和向其它对象发送信息。面向对象一直是软件开发领域内比较热门的话题,首先,面向对象符合人类看待事物的一般规律。其次,采用面向对象方法可以使系统各部分各司其职、各尽所能。为编程人员敞开了一扇大门,使其编程的代码更简洁、更易于维护,并且具有更强的可重用性。有人说PHP不是一个真正的面向对象的语言,这是事实。PHP 是一个混合型语言,你可以使用OOP,也可以使用传统的过程化编程。然而,对于大型项目,你可能需要在PHP 中使用纯的OOP去声明类,而且在你的项目里只用对象和类。这个概念我先不多说了,因为有很多朋友远离面向对象编程的主要原因就是一接触面向对象概念的时候就理解不上去,所以就不想去学下去了。等读者看完整体内容后再去把概念搞明白吧。
2.什么是类,什么是对象,类和对象这间的关系 类的概念:类是具有相同属性和服务的一组对象的集合。它为属于该类的所有对象提供了统一的抽象描述,其内部包括属性和服务两个主要部分。在面向对象的编程语言中,类是一个独立的程序单位,它应该有一个类名并包括属性说明和服务说明两个主要部分。
对象的概念:对象是系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位。一个对象由一组属性和对这组属性进行操作的一组服务组成。从更抽象的角度来说,对象是问题域或实现域中某些事物的一个抽象,它反映该事物在系统中需要保存的信息和发挥的作用;它是一组属性和有权对这些属性进行操作的一组服务的封装体。客观世界是由对象和对象之间的联系组成的。 类与对象的关系就如模具和铸件的关系,类的实例化结果就是对象,而对一类对象的抽象就是类。类描述了一组有相同特性(属性)和相同行为(方法)的对象。
3.什么是面向对象编程呢? 就不说他的概念,如果你想建立一个电脑教室,首先要有一个房间,房间里面要有N台电脑,有N张桌子, N把椅子,白板,投影机等等,这些是什么,刚才咱们说了,这就是对象,能看到的一个个的实体,可以说这个电脑教室的单位就是这一个个的实体对象,它们共同组成了这个电脑教室,那么我们是做程序,这和面向对象有什么关系呢?开发一个系统程序和建一个电脑教室类似,你把每个独立的功能模块抽象成类,形成对象,由多个对象组成这个系统,这些对象之间都能够接收信息、处理数据和向其它对象发送信息等等相互作用。就构成了面向对象的程序。
4.如何抽象出一个类? 上面已经介绍过了,面向对象程序的单位就是对象,但对象又是通过类的实例化出来的,所以我们首先要做的就是如何来声明类,做出来一个类很容易,只要掌握基本的程序语法定义规则就可以做的出来,那么难点在那里呢?一个项目要用到多少个类,用多少个对象,在那要定义类,定义一个什么样的类,这个类实例化出多少个对象,类里面有多少个属性,有多少个方法等等,这就需要读者通过在实际的开发中就实际问题分析设计和总结了。 类的定义: class 类名{ }
使用一个关键字class和后面加上一个你想要的类名以及加上一对大括号, 这样一个类的结构就定义出来了,只要在里面写代码就可以了,但是里面写什么? 能写什么?怎样写才是一个完整的类呢?上面讲过来,使用类是为了让它实例出对象来给我们用,这就要知道你想要的是什么样的对象了,像上面我们讲的一个装机配置单上写什么,你装出来的机子就有什么。比如说,一个人就 是一个对象,你怎么把一个你看好的人推荐给你们领导呢?当然是越详细越好了: 首先,你会介绍这个人姓名、性别、年龄、身高、体重、电话、家庭住址等等。 然后,你要介绍这个人能做什么,可以开车,会说英语,可以使用电脑等等。 只要你介绍多一点,别人对这个人就多一点了解,这就是我们对一个人的描述, 现在我们总结 一下,所有的对象我们用类去描述都是类似的,从上面人的描述可以看到, 做出一个类来,从定义的角度分两部分,第一是从静态上描述,第二是从动态上描述,静态上的描述就是我们所说的
属性,像上面我们看到的,人的姓名、性别、年龄、身高、体重、电话、家庭住址等等。动态上也就是人的这个对象的功能,比如这个人可以开车,会说英语,可以使用电脑等等,抽象成程序时,我们把动态的写成函数或者说是方法,函数和方法是一样的。所以,所有类都是从属性和方法这两方面去写,属性又叫做这个类的成员属性,方法叫做这个类的成员方法。 class 人{ 成员属性:姓名、性别、年龄、身高、体重、电话、家庭住址 成员方法:可以开车, 会说英语, 可以使用电脑 } 属性: 通过在类定义中使用关键字" var “(如果没有别的关键词修饰,则用var来修饰)来声明变量,即创建了类的属性,虽然在声明成员属性的时候可以给定初始值, 但是在声明类的时候给成员属性初使值是没有必要的,比如说要是把人的姓名赋上“张三”,那么用这个类实例出几十个人,这几十个人都叫张三了,所以没有必要, 我们在实例出对象后给成员属性初始值就可以了。 如: var $somevar; 方法(成员函数): 通过在类定义中声明函数,即创建了类的方法。 如: function somefun(参数列表) { … … }
上面就是一个类的声明,从属性和方法上声明出来的一个类,但是成员属性最好在声明的时候不要给初始的值,因为我们做的人这个类是一个描述信息,将来用它实例化对象,比如实例化出来10个人对象,那么这10个人, 每一个人的名子,性别, 年龄都是不一样的,所以最好不要在这个地方给成员属性赋初值,而是对每个对象分别赋值的。用同样的办法可以做出你想要的类了, 只要你能用属性和方法能描述出来的实体都可以定义成类,去实例化对象。为了加强你对类的理解,我们再做一个类,做一个形状的类,形状的范围广了点, 我们就做个矩形吧,先分析一下,想一想从两方面分析,矩形的属性都有什么?矩形的功能都有什么? class 矩形 { //矩形的属性 矩形的长; 矩形的宽;
//矩形的方法 矩形的周长; 矩形的面积; }
如果用这个类来创建出多个矩形对象,每个矩形对象都有自己的长和宽, 都可以求出自己的周长和面积了。
面向对象的三大特性
class Person { //下面是人的成员属性 private $name; //人的名子,被private封装上了 private $sex; //人的性别, 被private封装上了 private $age; //人的年龄, 被private封装上了 //这个人可以说话的方法 function say() { echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."
"; } //这个人可以走路的方法, 被private封装上了 private function run() { echo "这个人在走路"; } } //实例化一个人的实例对象 $p1=new Person(); //试图去给私有的属性赋值, 结果会发生错误 $p1->name="张三"; $p1->sex="男"; $p1->age=20; //试图去打印私有的属性, 结果会发生错误 echo $p1->name.”
”; echo $p1->sex.”
”; echo $p1->age.”
” //试图去打印私有的成员方法, 结果会发生错误 $p1->run(); ?>
function say() { echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."
"; //在这里也可以访问私有方法 //$this->run(); }
class Person { //下面是人的成员属性 private $name; //人的名子,被private封装上了 private $sex; //人的性别, 被private封装上了 private $age; //人的年龄, 被private封装上了 //定义一个构造方法参数为私有的属性姓名$name、性别$sex和年龄$age进行赋值 function __construct($name, $sex, $age) //此处如果不给予初始值,则实例化对象时new Person() 里要赋值,否则会有警告 { //通过构造方法传进来的$name给私有成员属性$this->name赋初使值 $this->name=$name; //通过构造方法传进来的$sex给私有成员属性$this->sex赋初使值 $this->sex=$sex; //通过构造方法传进来的$age给私有成员属性$this->age赋初使值 $this->age=$age; } //这个人可以说话的方法, 说出自己的私有属性,在这里也可以访问私有方法 function say() { echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."
"; } } //通过构造方法创建3个对象$p1、p2、$p3,分别传入三个不同的实参为姓名、性别和年龄 $p1=new Person(“张三”,”男”, 20); $p2=new Person(“李四”,”女”, 30); $p3=new Person(“王五”,”男”, 40); //下面访问$p1对象中的说话方法 $p1->say(); //下面访问$p2对象中的说话方法 $p2->say(); //下面访问$p3对象中的说话方法 $p3->say();
输出结果为: 我的名子叫:张三性别:男我的年龄是:20 我的名子叫:李四性别:女我的年龄是:30 我的名子叫:王五性别:男我的年龄是:40 因为构造方法是默认的公有方法(构造方法不要设置成私有的),所以在类的外面可以访问到,这样就可以使用构造方法创建对象,另外构造方法也是类里面的函数,所以可以用构造方法给私有的属性赋初值。Say()的方法是默认公有的,所以在外面也可以访问的到,说出他自己的私有属性。 从上面的例子中我们可以看到,私有的成员只能在类的内部使用,不能被类外部直接来存取,但是在类的内部是有权限访问的,所以有时候我们需要在类的外面给私有属性赋值和读取出来,也就是给类的外部提供一些可以存取的接口,上例中构造方法就是一种赋值的形式,但是构造方法只是在创建对象的时候赋值,如果我们已经有一个存在的对象了,想对这个存在的对象赋值,这个时候,如果你还使用构造方法传值的形式传值,那么就创建了一个新的对象,并不是这个已存在的对象了。所以我们要对私有的属性做一些可以被外部存取的接口,目的就是可以在对象存在的情况下,改变和存取属性的值,但要注意,只有需要让外部改变的属性才这样做,不想让外面访问的属性是不做这样的接口的,这样就能达到封装的目的,所有的功能都是对象自己来完成,给外面提供尽量少的操作。如果给类外部提供接口,可以为私有属性在类外部提供设置方法和获取方法,来操作私有属性.例如:
private $age; //私有的属性年龄 function setAge($age) //为外部提供一个公有设置年龄的方法 { if($age<0 ¦¦ $age>130) //在给属性赋值的时候,为了避免非法值设置给属性 return; $this->age=$age; } function getAge() //为外部提供一个公有获取年龄的方法 { return($this->age); }
上一节中,我们为每个属性做了设置和获取的方法,在PHP5中给我们提供了专门为属性设置值和获取值的方法,“__set()”和“__get()”这两个方法,这两个方法不是默认存在的,而是我们手工添加到类里面去的,像构造方法(__construct())一样, 类里面添加了才会存在,可以按下面的方式来添加这两个方法,当然也可以按个人的风格来添加:
//__get()方法用来获取私有属性 private function __get($property_name) { if(isset($this->$property_name)) { return($this->$property_name); }else { return(NULL); } } //__set()方法用来设置私有属性 private function __set($property_name, $value) { $this->$property_name = $value; }
"; if(isset($this->$property_name)) { return($this->$property_name); } else { return(NULL); } } //__set()方法用来设置私有属性 private function __set($property_name, $value) { echo "在直接设置私有属性值的时候,自动调用了这个__set()方法为私有属性赋值
"; $this->$property_name = $value; } } $p1=new Person(); //直接为私有属性赋值的操作, 会自动调用__set()方法进行赋值 $p1->name="张三"; $p1->sex="男"; $p1->age=20; //直接获取私有属性的值, 会自动调用__get()方法,返回成员属性的值 echo "姓名:".$p1->name."
"; echo "性别:".$p1->sex."
"; echo "年龄:".$p1->age."
"; ?>
private function __isset($nm) { echo "当在类外部使用isset()函数测定私有成员$nm时,自动调用
"; return isset($this->$nm); }
private function __unset($nm) { echo "当在类外部使用unset()函数来删除私有成员时自动调用的
"; unset($this->$nm); }
$property_name)) { return($this->$property_name); }else { return(NULL); } } //__set()方法用来设置私有属性 private function __set($property_name, $value) { $this->$property_name = $value; //这里的$this->$property_name 中$property_name 中要有$的,没有的话将赋不了值 } //__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 person name"; //在使用isset()函数测定私有成员时,自动调用__isset()方法帮我们完成,返回结果为true echo var_dump(isset($p1->name))."
"; echo $p1->name."
"; //在使用unset()函数删除私有成员时,自动调用__unset()方法帮我们完成,删除name私有属性 unset($p1->name); //已经被删除了, 所这行不会有输出 echo $p1->name; ?>