PHP 类与对象

面向对象

面向对象是一种计算机编程架构,比面向过程编辑具有更强的灵活性和扩展性。面向对象编辑也是一个程序员发展的“分水岭”,很多的初学者和略有成就的开发者,就是因为无法理解“面向对象”而放弃。这里想提醒一下初学者:要想在编程这条路上走得比别人远,就一定要掌握面向对象编程技术。

一、            面向对象的基本概念

这里所指的面向对象,准确地说应该叫做面向对象编程(OOP),是面向对象的一部分。面向对象包括3个部分:面向对象分析(Object OrientedAnalysis,OOA)、面向对象设计(Object Oriented Design,OOD)、以及面向对象编程(Object OrientedProgramming,OOP)。面向对象编程的两个重点概念是类和对象。

1.        类

世间万物都具有其自身的属性和方法,通过这些属性和方法可以将不同物质区分开来。例如,人具有身高,体重,以及肤色等属性,还可以进行吃饭、学习、走路等能动活动,这些活动可以说是人具有的功能。可以把人看作程序中的一个类,那么人的身高可以比作类中的属性,走路可以比作类中的方法。也就是说,类是属性和方法的集合,是面向对象编程方式的核心和基础,通过类可以将零散的用于实现某项功能的代码进行有效管理。

2.        对象

类只是具备某项功能的抽象模型,实际应用中还需要对类进行实例化,这样就引入了对象的概念。对象是类进行实例化后的产物,是一个实体。仍然以人为例,“黄种人是人”这句话没有错误,但过来说,”人是黄种人”这句话一定是错误的。因为除了有黄种人,还有黑人、白人等。那么“黄种人”就是“人”这个类的一个实例对象。可以就样理解对象和类的关系:对象实际上就是“有血有肉的、能摸得到看得到的“一个类。

3.        面向对象编程的三大特点

1)       封闭性

封闭性,也可以称为信息隐藏。就是将一个类的使用和实现分开,只保留有限的接口(方法)与外部联系。对于用到该类的开发人员,只要知道这个类如何使用即可,而不用去关心这个类是如何实现的。这样做可以让开发人员更好地把精力集中起来专注别的事情,同时也避免了程序之间的相互依赖而带来的不便。

2)       继承性

继承性就是派生类(子类)自动继承一个或多个基类(父类)中的属性与方法,并可以重写或添加新的属性和方法。继承这个特性简化了对象和类的创建,增加了代码的可重性。继承分单继承和多继承,PHP所支持的是单继承,也就是说,一个子类有且只有一个父类。

3)       多态性

多态性是指同一个类的不同对象,使用同一个方法可以获得不同的结果,这种技术称为多态性。多态性增强了软件的灵活性和重用性。

二、            PHP与对象

1.        类的定义

和很多面向对象的语言一样,PHP也是通过class关键字加类名来定义类的。类的格式如下:

<?php

Class myobject{

//……

}

?>

上述两个大括号中间的部分是类的全部内容,如上述myobject就是一个最简单的类了。Myobject类仅有一个类的骨架,什么功能都没有实现,但这并不影响它的存在。

注意:一个类,即一对大括号之间的全部内容都要在一段代码中,即一个<?php   ?>

之间不能分割成多块,例如:

<?php

class myobject{

//……

?>

<?php

//……

}

?>

这种格式是不允许的。

2.        成员方法

类中的函数被称为成员方法。函数和成员方法唯一的区别就是,函数实现的是某个独立的功能,而成员方法是实现类中的一个行为,是类的一部分。

下面就来扩充上面的myobject类,为它添加一个成员方法,代码如下:

<?php

classmyobject{

function getobjectname($name){

echo "商品名称为:".$name;

}

}

?>

该方法的作用是输出商品名称,商品名称是通过方法的参数传进来的。

3.        类的实例化

类的方法已经添加进去了,接下来就是使用方法,但使用方法不像使用函数那么简单。首先要对类进行实例化,实例化是通过关键字new来声明一个对象。然后使用如下格式来调用要使用的方法:

“对象名->成员方法”

类是一个抽象的描述,是功能相似的一组对象的集合。如果想用到类中的方法和变量,首先就要把它具体落实到一个实体,也就是对象上。

例:

<!DOCTYPEhtml PUBLIC "-//W3C//DTDXHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<htmlxmlns="http://www.w3.org/1999/xhtml">

<head>

<metahttp-equiv="Content-Type" content="text/html;charset=gb2312" />

<title>无标题文档</title>

</head>

<body>

<?php

class myobject{

function getobjectname($name){

echo "商品名称为:".$name;

}

}

$c_book=new myobject();           //实例化对象

echo $c_book->getobjectname("计算机图书");  //调用getbookname()方法

?>

</body>

</html>

4.        成员变量

类中的变量,也称为成员变量(也有称为属性或字段的)。成员变量用来保存信息数据,或与成员方法进行交互来实现某功能。

定义成员变量的格式为:

关键字 成员变量名

关键字可以使用public、private、protected、static和final中的任意一个。

访问成员变量和访问成员方法是一样的。只要把成员方法换成成员变量即可,格式为:

对象名->成员变量。

例:

<?php

class myobject{

public $object_name;

functionsetobjectname($name){

$this->object_name=$name;

}

functiongetobjectname(){

return$this->object_name;

}

}

$c_book=new myobject();

$c_book->setobjectname("计算机图书");

echo $c_book->object_name."<br>";

echo $c_book->getobjectname();

?>

程序说明:$this->作用是调用本类中的成员变量或成员方法,这里只要知道含义即可。无论是使用$this->还是使用对象名->的格式,后面接的变量是没有$符号的。这是一个出错几率很高的错误。

5.        类常量

既然有变量,当然也会有常量了。常量就是不会改变的量,是一个恒值。众所周知的一个常量就是圆周率Pi。定义常量使用关键字const如:

ConstPI=3.14159;

例:

<?php

class myobject{

const book_type="计算机图书";             //声明常量book_type

public $object_name;                                    //声明变量

functionsetobjectname($name){                     //声明方法setobjectname()

$this->object_name=$name;                       //设置成员的变量值

}

functiongetobjectname(){                //声明方法getobject()

return$this->object_name;

}

}

$c_book=new myobject();                                 //实例化对象

$c_book->setobjectname("HP的类");              //调用方法setobjectname

echo myobject::book_type."<br>";              //输出常量的值

echo $c_book->getobjectname();                 //调用方法getobjectname

?>

可以看出常量和变量的输出是不一样。常量不需要实例化对象,直接由类名+常量名调用即可。常量输出的格式为:

类名::常量名;

类名和常量名之间的两个冒号称为作用域操作符,使用这个操作符可以在不创建对象的情况下调用类的常量、变量和方法。

6.        构造方法和析构方法

1)       构造方法

当一个类实例化一个对象时,可能会随着对象初始化一些成员变量。

例:

<?php

class myobject{

public $object_name;   //商品名称

public $object_price;              //商品价格

public $object_num;        //商品数量

public $object_agio;        //商品折扣

…………

}

?>

声明一个myobject类的对象,并对这个类的一些成员变量赋初值。代码如下:

<?php

class myobject{

public $object_name;

public $object_price;

public $object_num;

public $object_agio;

functiongetobjectname(){

return$this->object_name;

return$this->object_price;

return $this->object_num;

return $this->object_agio;

}

}

$dress=new myobject();

$dress->object_name="western-style clothes";

$dress->object_price=1500;

$dress->object_num=5;

$dress->object_agio=8;

echo $dress->getobjectname();

?>

可以看到,如果赋初值比较多,写起来就比较麻烦。为此,PHP引入了构造方法。构造方法是生成对象时自动执行的成员方法,作用就是初始化对象。该方法可以没有参数,也可以有多个参数。构造方法的格式如下:

Void__construect([mixed args,[……]])

注意:函数中的__是两条下划线,不是一条。

例:

<?php

class myobject{

public $object_name;

public $object_price;

public $object_num;

public $object_agio;

function__construct($name,$price,$num,$agio){   //通过参数给成员变量赋值

$this->object_name=$name;

$this->object_price=$price;

$this->object_num=$num;

$this->object_agio=$agio;

}

function setobjectname($name){

$this->object_name=$name;

}

function getobjectname1(){

return $this->object_name;

}

function getobjectname2(){

return $this->object_price;

}

}

$c_book=new myobject("western-styleclothes",1500,5,8);

echo $c_book->getobjectname1();

echo "<br>";

echo $c_book->getobjectname2();

?>

可以看到,重写后的类,在实例化对象时只要一句话即可完成赋值工作。

构造方法是初始化对象时使用的。如果类中没有构造方法,那么PHP会自动生成一个。自动生成的构造方法没有任何参数,没有任何操作。

2)       析构方法

析构方法的作用和构造方法正好相反,是对象被销毁时被调用的,作用是释放内存。析构方法的格式为:

Void__destruct(void)

例:

<?php

class myobject{

public $object_name;

public $object_price;

public $object_num;

public $object_agio;

function__construct($name,$price,$num,$agio){   //通过参数给成员变量赋值

$this->object_name=$name;

$this->object_price=$price;

$this->object_num=$num;

$this->object_agio=$agio;

}

function setobjectname($name){

$this->object_name=$name;

}

function getobjectname1(){

return $this->object_name;

}

function getobjectname2(){

return $this->object_price;

}

function __destruct(){

echo "<p><b>对象被销毁,调用析构函数。</b></p>";

}

}

$c_book=new myobject("western-styleclothes",1500,5,8);

echo $c_book->getobjectname1();

echo "<br>";

echo $c_book->getobjectname2();

unset($c_book);

?>

PHP使用的是一种“垃圾回收”机制,自动清除不再使用的对象,释放内存。就是说即使不使用unset函数,析构方法也会自动被调用,这里只是明确一下析构函数在何时被调用。一般情况下是不需要手动创建析构方法的。

<?php

class myobject{

public $object_name;

public $object_price;

public $object_num;

public $object_agio;

function __construct($name,$price,$num,$agio){    //通过参数给成员变量赋值

$this->object_name=$name;

$this->object_price=$price;

$this->object_num=$num;

$this->object_agio=$agio;

}

function setobjectname($name){

$this->object_name=$name;

}

function getobjectname1(){

return$this->object_name;

}

function getobjectname2(){

return $this->object_price;

}

function __destruct(){

echo"<p><b>对象被销毁,调用析构函数。</b></p>";

}

}

$c_book=new myobject("western-styleclothes",1500,5,8);

echo $c_book->getobjectname1();

echo "<br>";

echo $c_book->getobjectname2();

?>

7.        继承和多态的实现

Myobject类是一个商品信息类。商品分为很多种电子类、书籍类、家居类等。各种商品类别之间有一些公共的属性。例如,都有一个商品的名称,都有一个商品的价格……但还会有许多不同之处,例如,电子类商品有功率,书籍有作者……如果都由一个myobject类来生成各个对象。除了那些公共属性外,其他属性和方法还需自己手动来写,工作效率提高不了多少。这时,可以使用面向对象中的继承来解决这个难题。

在PHP中实现继承是通过关键字extends来声明的,继承格式如下:

Class subclass extends superclass{

……

}

说明:subclass为子类的名称,superclass为父类名称。

例:

<?php

class myobject{

public $object_name;

public $object_price;

public $object_num;

public $object_agio;

function__construct($name,$price,$num,$agio){   //通过参数给成员变量赋值

$this->object_name=$name;

$this->object_price=$price;

$this->object_num=$num;

$this->object_agio=$agio;

}

function showme(){

echo "这句话会输出吗?答案是不会。";

}

}

class book extends myobject{

public $book_type;

function__construct($type,$num){

$this->book_type=$type;

$this->object_num=$num;

}

functionshowme(){                            //重写父类中的showme()方法。

return "本次新进".$this->book_type."图书".$this->object_num."本"."<br>";

}

}

class elec extends myobject{

function showme(){                             //重写父类中的showme()方法

return "热卖商品:".$this->object_name."<br>"."原价:".$this->object_price."<br>"."特价".$this->object_price*$this->object_agio;

}

}

$c_book=new book("计算机类",1000);   //声明一个book子类对象。

$h_elec=new elec("待机王XX系列",1200,3,0.8);    //声明一个elec子类对象。

echo$c_book->showme()."<br>";   //输出book子类的showme()方法

echo $h_elec->showme();          //输出elec子类的是showme()方法

?>

子类继承了父类的所有成员变量和方法,包括构造函数。这就是继承的实现。

当子类被创建时,PHP会先在子类中查找构造方法。如果子类有自己的构造方法,PHP会先调用子类中的方法,当子类中没有时,PHP则会去调用父类中的构造方法。

两个子类重写了父类的方法showme(),所以两个对象虽然调用的都是showme()方法,但返回的却是两段不同的信息。这就是多态性的实现。

8.        $this->和::的使用

子类不仅可以调用自己的变量和方法,也可以调用父类中的变量和方法,那么对于其他不相关的类成员还可以调用吗?答案是:可以。

1、$this->

在前面类的实例化中,对如何调用成员方法有了基本的了解,那就是用对象名加方法名,格式为“对象名->方法名”。但在定义类时(如myobject),根本无法得知对象的名称是什么。这时如果调用类中的方法,就要用伪变量$this->。$this的意思就是本身,所以$this->只可以在类的内部使用。

例:

<?php

classexample{   //创建类example

function exam(){   //创建成员方法

if(isset($this)){            //判断变量$this是否存在

echo "\$this的值为:".get_class($this);    //如果存在,输出$this所属类的名字

}else{

echo "$this未定义。";

}

}

}

$class_name=newexample();   //实例化对象

$class_name->exam();          //调用方法exam()

?>

Get_class函数返回对象所属类的名字,如果不是对象,则返回false。

2、操作符::

相比伪变量$this只能在类的内部使用,操作符::可是真正的强大。操作符::可以在没有声明任何实例的情况下访问类中的成员方法和成员变量。使用::操作符的通用格式为:

关键字::变量名/常量名/方法名

这里的关键字分为3种情况:

Parent关键字:可以调用父类中的成员变量、成员方法和常量。

Self关键字:可以调用当前类中的静态成员和常量。

类名:可以调用本类中的变量、常量和方法。

例:

<?php

class book{

const name="conputer";      //声明常量name

function __construct(){        //构造方法

echo "本月图书类冠军为:".book::name."<br>";   //输出默认值

}

}

class l_book extends book{          //book类的子类

const name="foreign language";      //声明常量

function __construct(){                  //子类的构造方法

parent::__construct();       //调用父类的构造方法

echo "本月图书类冠军为:".self::name;    //输出本类中的默认值

}

}

$obj=new l_book();

?>

说明:关于静态方法(变量)的声明及使用可参考以下内容。

9.        数据隐藏

面向对象编辑的特点之一是封装性,即数据隐藏。可在前面的学习中并没有突出这一点。对象中的所有变量和方法可以随意调用,甚至不用实例化也可以使用类中的方法、变量。这就是面向对象吗?

这当然不算是真正的面向对象。关键字public、private、protected、static和final。这就是用来限定类成员(包括变量和方法)的访问权限。

成员变量和成员方法在关键字的使用上都是一样的。这里只以成员变量为例说明几种关键字的不同用法。对于成员方法同样适用。

1、 public公共成员

顾名思义,就是可以公开的、没有必要隐藏的数据信息。可以在程序的任何地点(类内、类外)被其他的类和对象调用。子类可以继承和使用父类中所有的公共成员。

所有的变量都被声明为public,而所有的方法在默认的状态下也是public。所以对变量

和方法的调用显示得十分混乱。为了解决这个问题,就需要使用第二个关键字:private。

2、 private私有成员

被private关键字修饰的变量和方法,只能在所属类的内部被调用和修改,不可以在类外被访问。在子类中也不可以。

例:

<?php

class book{

private $name="computer";

public function setname($name){

$this->name=$name;

}

public function getname(){

return $this->name;

}

}

class lbook extends book{

}

$lbook=new lbook();

echo "正确操作私有变量的方法:";

$lbook->setname("HP应用开发!");

echo $lbook->getname();

echo "直接操作私有变量的结果:";

echo book:name;

?>

对于成员方法,如果没有写关键字,那么默认就是public。从本节开始,以后所有的方法及变量都会带个关键字,这是一种良好的书写习惯。

3、 protected保护成员

private关键字可以将数据完全隐藏起来,除了在本类外,其他地方都不可以调用。子类也不可以。但对于有些变量希望子类能够调用,但对另外的类来说,还要做到封装。这时,就可以使用protected。被protected修改的类成员,可以在类和子类中被调用,其他地方则不可以被调用。

例:

<?php

class book{

protected $name="computer";

}

class lbook extends book{

public function showme(){

echo "对于protected修饰的变量,在子类中是可以直接调用的。如:\$name=".$this->name."<br>";

}

}

$lbook=new lbook();

$lbook->showme();

echo "但在其他的地方是不可以调用的,否则:";

$lbook->name="history";

?>

虽然PHP中没有对修饰变量的关键字做强制性的规定和要求,但从面向对象的特征和设计方面考虑,一般使用private或protected关键字来修饰变量,以防止变量在类外被直接修改和调用。

10.    静态变量(方法)

不是所有的变量(方法)都要通过创建对象来调用的。可以通过给变量(方法)加上static关键字来直接调用。调用静态成员的格式为:

关键字::静态成员

关键字可以是:

Self:在类内部调用静态成员时所使用。

静态成员所在的类名,在类外调用类内部的静态成员时所用。

注意:在静态方法中,只能调用静态变量,而不能调用普通变量,而普通方法则可以调用静态变量。

使用静态成员,除了可以不需要实例化对象,另一个作用就是在对象被销毁后,仍然保存被修改的静态数据。以便下次继续使用。这个概念比较抽象,下面结合一个实例说明。

例:

<?php

class book{

static $num=0;

public function showme(){

echo "您是第".self:num."位访客。";

self:num++;

}

}

$book1=new book();

$book1->showme();

echo "<br>";

$book2=new book();

$book2->showme();

echo "<br>";

echo "您是第".book:num."为访客。";

?>

如果将程序代码中的静态变量改为普通变量,如private $num=0;,那么结果就不一样。

说明:静态成员不用实例化对象,当类第一次被加载时就已经分配了内存空间,所以直接调用静态成员的速度要快一些。但如果静态成员声明得过多,空间一直被占用,反而会影响系统的功能。这个尺度只能通过实践、积累,才能真正地把握。

三、            PHP对象的高级应用

1.        final关键字

final,中文含义是最终的、最后的。被final修饰过的类和方法就是“最终版本”;

如果有一个类的格式为:

Final class class_name{

}

说明该类不可以再被继承,也不能再有子类。

如果有一个方法的格式为:

Final function method_name();

说明该方法在子类中不可以进行重写,也不可以被覆盖。

例:

<?php

final class myobject{

function __construct(){

echo "initialize object";

}

}

class mybook extends myobject{

static function exam(){

echo "you can‘t see me.";

}

}

mybook::exam();

?>

输出的结果是:

Fatal error: Class mybookmay not inherit from final class (myobject) inC:\webserver\wwwroot\2.phpon line 19

2.        抽象类

抽象类是一种不能被实例化的类,只能作为其他类的父类来使用。抽象类使用abstract关键字来声明,格式为:

Abstract class abstractname{

}

抽象类和普通类相似,都包含成员变量、成员方法。两者的区别在于,抽象类至少要包含一个抽象方法。抽象方法没有方法体,其功能的实现只能在子类中完成。抽象方法也是使用abstract关键字修饰的。它的格式为:

Abstractfunction abstractname();

注意:在抽象方法后面要有分号“;”

抽象类和抽象方法主要应用于复杂的层次关系中,这种层次关系要求每一个子类都包含并重写某些特定的方法。举一个例子:中国的美食是多种多样的,有吉菜、鲁菜、川菜、粤菜等。每种菜系使用的都是煎、炒、炸等手法,只是在具体的步骤上,各有各的不同。如果把中国美食当作一个大类cate,下面的各大菜系就是cate的子类,而煎炒烹炸则是每个类中都有的方法。每个方法在子类中的实现都是不同的,在父类中无法规定。为了统一规范,不同子类的方法要有一个相同的方法名:decoct(煎)、stir_fry(炒)、cook(烹)、fry(炸)。

例:

<?php

/* 抽象类myobject */

abstract class myobject{    //抽象方法servie

abstract functionservice($getname,$price,$num);

}

//声明抽象类的子类mybook

class mybook extends myobject{    //实现抽象方法service

function service($getname,$price,$num){

echo "您购买的商品是".$getname.",该商品的价格是:".$price."元";

echo "您购买的数量为:".$num."本。";

echo "如发现缺页、损坏、请在3日内更换。";

}

}

//声明另一个抽象类的子类mycomputer

class mycomputer extends myobject{   //实现抽象方法service

function service($getname,$price,$num){

echo "您购买的商品是:".$getname.",该商品的价格是:".$price."元。";

echo "您购买的数量为:".$num."台。";

echo "如发生非人为质量问题,请在3个月内更换。";

}

}

$book=new mybook();    //实例化对象$book

$computer=new mycomputer();   //实例化对象$computer

$book->service("《PHP从入门到精通》",85,3);   //调用$book对象的service方法

echo "<br />";

$computer->service("XX笔记本",8500,1);    //调用computer对象的service方法

?>

3.        接口的使用

继承特性简化了对象、类的创建,增加了代码的可重性。但PHP只支持单继承。如果想实现多重继承,就要使用接口。PHP可以实现多个接口。

接口类通过interface关键字来声明,并且类中只能包含未实现的方法和一些成员变量,格式如下:

Interface interfacename{

Function interfacename1();

Function interfacename2();

………………

}

注意:不要用public以外的关键字来修饰接口中的类成员,对于方法,不写关键字也可以。这是一个接口类自身的天性决定的。

子类是通过implements关键字来实现接口的,如果要实现多个接口,那么每个接口之间使用逗号“,”连接。而且所有未实现的方法需要在子类中全部实现,否则PHP将会出现错误。格式如下:

Class subclass implementsinterfacename1,interfacename2{

Function interfacename1(){

//功能实现

}

Function interfacename2(){

//功能实现

}

…………

}

例:本例首先声明了两个接口mpopedom和mpurview,接着声明了两个类member和manager,其中member类继承了mpopedom接口;manager继承了mpopedom和mpurview接口。分别实现各自的成员方法后,实例化两个对象$member和$manager。最后调用实现的方法。

<?php

interface mpopedom{

function popedom();

}

interface mpurview{

function purview();

}

class member implements mpurview{

function purview(){

echo "会员拥有的权限";

}

}

class manager implements mpurview,mpopedom{

function purview(){

echo "管理员拥有会员的全部权限。";

}

function popedom(){

echo "管理员还有会员没有的权限。";

}

}

$member=new member();

$manager=new manager();

$member->purview();

echo "<br />";

$manager->purview();

$manager->popedom();

?>

通过上面的实例可以发现,抽象类和接口实现的功能十分相似。抽象类的优点是可以在抽象类中实现公共的方法,而接口则可以实现多继承。至于何时使用抽象类和接口就要看具体实现了。

4.        克隆对象

(1)、克隆对象

在PHP4中,对象被当作普通的数据类型来使用。如果想引开对象,需要使用&来声明,否则会按照PHP4的默认方式来按值传递对象。

例:本实例首先实例化一个myobject类的对象$book1,$book1的默认值是book,然后将对象$book1使用普通数据类型的赋值方式给对象$book2赋值。改变$book2的值为computer,再输出对象$book1的值。

<?php

classmyobject{

private $object_type="book";

public function settype($type){

$this->object_type=$type;

}

public function gettype(){

return $this->object_type;

}

}

$book1=new myobject();

$book2=$book1;

$book2->settype("computer");

echo "对象\$book1的值为:".$book1->gettype();

?>

上面的实例,在PHP5中的返回值为:对象$book1的值为:computer。

因为$book2只是$book1的一个引用,而在PHP4中的返回值是:对象$book1的值为:book,因为对象$book2是$book1的一个备份。

在PHP5中如果需要将对象复制,也就是克隆一个对象。需要使用关键字clone来实现。克隆一个对象的格式为:

$object1=new classname();

$object2=clone $object1;

(2)、__clone()方法

有时除了单纯地克隆对象外,还需要克隆出来的对象可以拥有自己的属性和行为。这时就可以使用_clone()方法来实现。__clone()方法的作用是:在克隆对象的过程中,调用_clone()方法,可以使用克隆出来的对象保持自己的一些行为及属性。

例:

<?php

class myobject{

private $object_type="book";

public function settype($type){

$this->object_type=$type;

}

public function gettype(){

return $this->object_type;

}

public function __clone(){

$this->object_type="computer";

}

}

$book1=new myobject();

$book2=clone $book1;

echo "对象$book1的变量值为:".$book1->gettype();

echo"<br />";

echo "对象$book2的变量值为:".$book2->gettype();

?>

5.        对象比较

通过克隆对象,相信读者已经理解表达式$boject2=$object1和$object2=clone $object1所表示的不同含义。但在实际开发中,应如何判断两个对象之间的关系是克隆还是引用?

这是可以使用比较运算符==和===。两个等号是比较两个对象的内容,3个等号===是比较对象的引用地址。

例:

<?php

classmyobject{

private $name;

function __construct($name){

$this->name=$name;

}

}

$book=new myobject(book);

$clonebook=clone $book;

$referbook=$book;

if($clonebook==$book){

echo "两个对象的内容相等。<br />";

}

if($referbook===$book){

echo "两个对象的引用地址相等。<br />";

}

?>

6.        对象类型检测

Instanceof操作符可以检测当前对象是属于哪个类的。一般格式如为:

Objectname instanceof classname

例:本实例首先创建两个类,一个基类(myobject)与一个子类(mybook)。实例化一个子类对象,判断对象是否属于该子类,再判断对象是否属于基类。

例:

<?php

classmyobject{}

class mybook extends myobject{

private $type;

}

$cbook=new mybook();

if($cbook instanceof mybook){

echo "对象\$cbook属于mybook类<br />";

}

if($cbook instanceof myobject){

echo "对象\$book属于myobject类<br />";

}

?>

7.        魔术方法(_)

PHP中有很多以两个下划线开头的方法,如前面已经介绍过的__construct()、__destruct()和__clone(),这些方法被称为魔术方法。下在我们将学习其他一些魔术方法。

注意:PHP中保留了所有以”__”开头的方法,所以只能使用在PHP文档中有的这些方法,不要自己创建。

(1)、__set()和__get()方法

这两个魔术方法的作用为:

当程序试图写入一个不存在或不可见的成员变量时,PHP就会执行__set()方法。__set()方法包含两个参数,分别表示变量名称和变量值。两个参数不可省略。

当程序调用一个未定义或不可见的成员变量时,可以通过__get()方法来读取变量值。__get()方法有一个参数,表示要调用的变量名。

注意:如果希望PHP调用这些魔术方法,那么首先必须在类中进行定义;否则PHP不会执行未创建的魔术方法。

例:

<?php

class myobject{

private $type="";

private function __get($name){

if(isset($this->$name)){

echo "变量".$name."的值为:".$this->$name."<br />";

}

else{

echo "变量".$name."未定义,初始化为0<br />";

$this->$name=0;

}

}

private function __set($name,$value){

if(isset($this->$name)){

$this->$name=$value;

echo "变量".$name."赋值为:".$value."<br />";

}else{

$this->$name=$value;

echo "变量".$name."被初始化为:".$value."<br />";

}

}

}

$mycomputer=new myobject();

$mycomputer->type="DIY";

$mycomputer->type;

$mycomputer->name;

?>

(2)、__call()方法

__call()方法的作用是:当程序试图调用不存在或不可见的成员方法时,PHP会先调用__call()方法来存储方法名及其参数。__call()方法包含两个参数,即方法名和方法参数。其中,方法参数是以数组形式存在的。

例:

<?php

class myobject{

public function mydream(){

echo "调用的方法存在,直接执行此方法:<br />";

}

public function __call($method,$parameter){

echo "如果方法不存在,则执行__call()方法。<br/>";

echo "方法名为:".$method."<br />";

echo "参数有:";

var_dump($parameter);

}

}

$exam=new myobject();

$exam->mydream();

$exam->mdreadm(‘how‘,‘what‘,‘why‘);

?>

(3)、sleep()和__wakeup()方法

使用serialize()函数可以实现序列化对象。就是将对象中的变量全部保存下来,对象中的类则只保存类名。在使用serialize()函数时,如果实例化的对象包含__sleep()方法,则会执行__sleep()方法。该方法可以清除对象并返回一个该对象中所有变量的数组。使用__sleep()方法的目的是关闭对象可能具有的数据库连接等类似的善后工作。

Unserialize()函数可以重新还原一个被serialize()函数序列化的对象,__wakeup()方法则是恢复在序列化中可能丢失的数据库连接及相关工作。

例:

<?php

class myobject{

private $type="DIY";

public function gettype(){

return $this->type;

}

public function __sleep(){

echo "使用serialize()函数将对象保存起来,可以存放到文本文件、数据库等地方。<br />";

return $this;

}

public function __wakeup(){

echo "当需要该数据时,使用unserialize()函数对已序列化的字符串进行操作,将其转换回来对象。<br />";

}

}

$mybook=new myobject();

$i=serialize($mybook);

echo "序列化后的字符串:".$i."<br />";

$rebook=unserialize($i);

echo "还原后的成员变量:".$rebook->gettype();

?>

(4)、tostring()方法

魔术方法这个作用是:当使用echo 或print输出对象时,将对象转化为字符串。

例:

<?php

class myobject{

private $type="DIY";

public function __tostring(){

return $this->type;

}

}

$mycomputer=new myobject();

echo "对象\$mycomputer的值为:";

echo $mycomputer;

?>

(5)、autoload()方法

将一个独立、完整的类保存到一个PHP页中,并且文件名和类名保持一致,这是每个开发人员者需要养成的良好习惯。这样,在下次重复使用某个类时即能很轻易地找到它。但还有一个问题是让开发人员头疼不已的,如果要在一个页面中引进很多的类,需要使用include_once()函数或require_once()函数一个一个地引入。

PHP5解决了这个问题,__autoload()方法可以自动实例化需要使用的类。当程序要用到一个类,但该类还没有被实例化时,PHP5将使用__autoload()方法,在指定的路径下自动查找和该类名称相同的文件。如果找到,程序则继续执行,否则,报告错误。

例:

Myobject.class.php页面代码如下:

<?php

classmyobject{

private $cont;

public function __construct($cont){

$this->cont=$cont;

}

public function __tostring(){

return $this->cont;

}

}

?>

Index.php页面代码如下:

<?php

function__autoload($class_name){

$class_path=$class_name.‘.class.php‘;

if(file_exists($class_path)){

include_once($class_path);

}else{

echo "类路径错误。";

}

}

$mybook=new myobject("江山代有人才出    各领风骚数百年");

echo $mybook;

?>

更多PHP 学习资料

尽在 爱思社区(http://bbs.aseoe.com/forum.phpmod=forumdisplay&fid=41&filter=typeid&typeid=17)

时间: 2024-08-06 03:40:33

PHP 类与对象的相关文章

Java 第七章 类和对象 笔记

一.对象的特征--类的属性 每个对象的每个属性都有特定的值 对象的操作--类的方法 二.封装:对象同时具有属性和方法两项特性.     对象的属性和方法通常被封装在一起,共同体现事物的特性,     二者相辅相成,不能分割. 三.类和对象的区别:     类:抽象的概念,是一个模子,确定了对象的属性和方法.    对象:能够看得见摸得着的实物.具有静态和动态特征. 四.定义类的步骤:     1.定义类名      2.定义类的属性 访问修饰符 属性类型 属性名称=默认值:     3.定义类的

类与对象

1.1 类和对象的关系   为什么要采用面向对象思想进行程序设计与开发 1.可以实现代码的复用 2.符合人思考的方式   类和对象的定义 1.类的定义:用class关键修饰的叫做类 2.对象的定义:类名定义的数据类型   类和对象之间关系 1.由对象归纳为类,是归纳对象共性的过程 2.在类的基础上,将状态和行为实体化为对象的过程为实例化   1.2 定义类   定义类的语法,类主要由成员变量和成员方法构成(暂不提构造函数) eg: publicclassStudent { //成员变量 intn

【编程语言】Java中的类和对象learn by Imooc

 一.什么是类和对象 * 类是模子,确定对象将会拥有的特征(属性)和方法 * 类的特点: *     类是对象的类型 *     具有相同属性和方法的一组对象的集合 * 对象的属性 *     属性-对象具有的各种特征 *     每个对象的每个属性都有用的特定值 * 对象的方法 *     方法-对象执行的操作(能干什么) * 类和对象的关系 *     类是抽象的概念,仅仅是模板 *     对象是一个你能够看得到,摸得着的具体实体 二. 如何定义Java的类 * 1.类的重要性:所有Jav

C++ 成员变量是别的类的对象

?在成员函数中,可以将this指针当参数传递,也可以返回this指针,或返回通过this指针拿到的对象 /* 成员变量是别的类的对象 */ #include <iostream> using namespace std; //日期类 class Date { int year,month,day; public: //构造方法 Date(){ cout << "Date() " << endl; } //有参 Date(int _y,int _m,i

l类与对象课后作业

java 的初始化规律 执行类成员定义时指定的默认值或类的初始化块,到底执行哪一个要看哪一个“排在前面”. 执行类的构造函数. 类的初始化块不接收任何的参数,而且只要一创建类的对象,它们就会被执行.因此,适合于封装那些“对象创建时必须执行的代码” 当多个类之间有继承关系时,创建子类对象会导致父类初始化块的执行. 请自行编写示例代码验证以上结论. public class InitializeBlockDemo { /**   * @param args   */ public static vo

第五节 类和对象

面向对象怎么理解? 1.1 面向对象是相对面向过程而言 1.2 面向对象和面向过程都是一种思想 1.3 面向过程:强调的是功能行为 1.4 面向对象:将功能封装进对象,强调具备了功能的对象 1.5 面向对象是基于面向过程的 特点: 三个特征:封装.继承.多态 我们在开发过程中,就是在找对象进行使用,没有对象就new一个对象. 找对象:建立对象,使用对象,维护对象的关系 封装: (1)是指隐藏对象的属性和实现细节,仅对外提供公共访问方式. (2)好处:将变化隔离:便于使用:提供重用性:提高安全性

C++笔记二:类和对象

类和对象 1:面向对象基础 2: 定义类和对象 3: 类和对象的使用 4: 构造函数和析构函数 5: this指针和复制构造函数 6: static静态成员 7: const对象和const成员 8: friend友元 ---------------------------------------------------------------------------------------------------------------------- (1)面向对象基础 一.什么是面向对象程序

类、对象和包

相关概念: 对象: 对象是存在的具体实体,具有明确定义的特征和行为. 类:是具有相同属性和行为的一组对象的集合.类是对象的抽象,对象是类的实例. 包:包就是文件夹.利用包可以可以组织相关的类,同时可以做到信息的隐藏. 属性:属性用于描述对象的特征.由于属性是属于一个对象的组成,所以属性也叫成员变量.属性跟随对象放在堆空间中,书写在类中,在方法之外,随对象产生而产生,随对象销毁而销毁.特点:属性用于描述对象的特征,对象之间彼此独立,一个对象属性的变化不会影响其他对象属性的变化.属性通过对象. 的方

8.python之面相对象part.1(初识类与对象)

一.类和对象的概念. 什么是类 类就是把一类事物相同的特征和动作整合到一起就是类比如说"人"就是一个类. 什么是对象 对象就是基于类创建出来的一个具体存在的事物这个事物包含了将其创造出来的类的特征和动作. 类与对象有什么关系一切的对象都是由类产生的假如说造一支笔首先要有一个造笔的模版上帝制造人也是一样制造一个人也需要一个造人的模版这个模板就是人的"类"然后根据类的定义来产生一支支笔和一个个的人. 什么是实例化 由类产生对象的过程就是实例化类实例化的结果就是一个对象对

Java —类和对象

类和对象 类是对象的类型,是具有相同的属性和方法的一组对象的集合. 定义类 访问修饰符 class 类名 { 数据类型 属性名: 访问修饰符 返回值类型 方法名 {} } 创建对象:类名 对象名 = new 类名(); 使用对象:引用对象的属性:对象名.属性名;引用对象的方法:对象名.方法名(); 可以基于一个类创建多个该类的对象,每个对象都拥有自己的成员,互相独立. 成员变量和局部变量 成员变量:在类中定义,描述对象将要有什么.可以在本类的方法或其他类的方法中使用.java会给成员变量一个初始