您的位置:首页 > 编程语言 > PHP开发

PHP入门学习7

2008-05-16 13:48 309 查看
在PHP中,简单地讲,类是执行一特定任务的程序语句的集合。一个典型的类的定义包含变量和函数两部分,并且充当从中生成该类的特定实例的模板。类的这些特定实例被称为对象。每个对象都有确定的特征或者属性以及确定的预先定义的函数或方法。对象的这些属性和方法直接对应于类定义中的变量和函数。一旦类得到定义,PHP允许你生成你想生成的多个实例。这些实例中的每一个都是具有各自属性及方法的完全独立的对象,而且因此可以独立于其他对象而被操作。这在你需要生成对象的多个实例的情况(例如,两个并发查询的两个并发数据库链接,或者两个购物车)时可以用得着。

类也允许你保持你的代码的模块性(你可以在单独的文件中定义一个类,且仅在你打算使用该类的脚本中包含该文件)和简化代码的更改,因为你只需要编辑一单独的文件来为你所有生成的对象增加新功能即可。

关于“类”的实际例子

为了更好的理解,我们选择一个动物,任何动物都可以。我选择熊,因为我喜欢熊。现在,请问你自己,你能否在OOP的框架下,将这头熊看做是一个“对象”?为什么不呢?毕竟,每只熊都有特定的特征:年龄、体重、性别---这些都相当于对象属性。而且每只熊可以执行特定的活动:吃、睡、走、跑、交配---所有这些都相当于对象方法。

让我们再稍微进一步。因为所有的熊都共享某些特定的特征,所以设想一个Bear()模板是可能的,该模板定义了这个星球上每只熊的基本特征和能力。一旦这个Bear()(“类”)用于创建新的变量$bear(“对象”),那么新创建的熊的个体特征可以独立于其他用这个模板来创建的熊而被操作。

现在,如果你坐下来使用PHP 5编写该类代码,那么它可能会看起来像下面这个样子:

<?php
// PHP 5
// class definition
class Bear {
// define properties
public $name;
public $weight;
public $age;
public $sex;
public $colour;
// define methods
public function eat() {
echo $this->name." is eating... ";
}
public function run() {
echo $this->name." is running... ";
}
public function kill() {
echo $this->name." is killing prey... ";
}
public function sleep() {
echo $this->name." is sleeping... ";
}
}
?>


给出这个类后,现在可以很容易地生成和你想要的一样多的熊,然后调整每只熊的个体属性。请看:

<?php
// my first bear
$daddy = new Bear;
// give him a name
$daddy->name = "Daddy Bear";
// how old is he
$daddy->age = 8;
// what sex is he
$daddy->sex = "male";
// what colour is his coat
$daddy->colour = "black";
// how much does he weigh
$daddy->weight = 300;
// give daddy a wife
$mommy = new Bear;
$mommy->name = "Mommy Bear";
$mommy->age = 7;
$mommy->sex = "female";
$mommy->colour = "black";
$mommy->weight = 310;
// and a baby to complete the family
$baby = new Bear;
$baby->name = "Baby Bear";
$baby->age = 1;
$baby->sex = "male";
$baby->colour = "black";
$baby->weight = 180;
// a nice evening in the Bear family
// daddy kills prey and brings it home
$daddy->kill();
// mommy eats it
$mommy->eat();
// and so does baby
$baby->eat();
// mommy sleeps
$mommy->sleep();
// and so does daddy
$daddy->sleep();
// baby eats some more
$baby->eat();
?>


正如上面所展示的解释那样,一旦新的对象被定义,它们的个体方法和属性可以相互独立的被访问和修改。这个会派上用场的,本次教程的剩余部分将会说明这一点。

类定义的本质

既然你已经直接理解了概念,那么让我们看看类定义的本质。

<?php
// PHP 5
// class definition
class Bear {
// define public properties
public $name;
public $age;
// more properties
// define public methods
public function eat() {
echo $this->name." is eating... ";
// more code
}
// more methods
}
?>


每个类定义都以紧跟着类的名字的关键字class开始。你可以给你自己的类任意你可以想像的到的名字,只要它不与PHP中所保留的字相冲突即可。一对大括号包含了所有的类变量和函数,这些类变量和函数被编写,正如你通常对他们编写代码一样。

PHP 5也将可见性概念引入对象模型中。可见性控制了对象属性和方法被调用者操作的程度,且它在定义如何打开和关闭你的类中起着重要的作用。存在着三个层次的可见性,范围从最可见的到最不可见的:公开的、私有的和保护的。在类的定义中,你可以通过在属性或者方法之前使用关键字(public、private或protected)之一来标记其可见性。

缺省情况下,类方法和属性是公开的;这允许调用脚本以触及到对象实例内部,然后直接操作这些对象实例。如果你不喜欢这种侵入的思想,那么你可根据你想对对象内部构件放弃多少控制来将某个属性或方法标记为私有的或者保护的(简言之,不止这些)。

因为PHP 4对象模型不包含对可见性的支持,所以上述类定义将无法在PHP 4中实现。相反,你将需要使用下列的方法:

<?php
// PHP 4
// class definition
class Bear {
// define properties
var $name;
var $weight;
var $age;
var $sex;
var $colour;
// define methods
function eat() {
echo $this->name." is eating... ";
}
function run() {
echo $this->name." is running... ";
}
function kill() {
echo $this->name." is killing prey... ";
}
function sleep() {
echo $this->name." is sleeping... ";
}
}
?>


从上面可以看出,PHP 4中的类属性和方法总是公开的。而且,你对此无能为力!

为了创建类的一个新实例,你可以使用关键字new将新创建的对象赋值给一个PHP变量。

<?php
$daddy = new Bear;
?>


在英语中,上述代码的含义是:创建类Bear()的一个新对象,然后将其赋值给变量$daddy。

现在你可以通过这个变量来访问类的所有方法和属性。比如,下列代码:

<?php
$daddy->name = "Daddy Bear";
?>


其含义是:“将值Daddy Bear赋给类Bear()的特定实例的变量$name”。 再来看下面:

<?php
$daddy->sleep();
?>


上述语句的含义是:“执行类Bear()的特定实例的sleep()函数”。

请注意:->符号用于将对象连接到它们的属性或者方法,以及该事实:当访问一个类实例的属性时符号$被忽略了。

如何访问类变量和类函数

倘若你需要在类定义自身的内部访问它的函数或者变量,那么PHP 4和PHP 5均提供了$this关键字,该$this关键字用于指向“本“类。为了明白这个是如何工作的,让我们改变eat()方法以接受食物单元,然后将其加到熊的体重上。

<?php
// PHP 5
// class definition class Bear {
// define properties     public $name;
public $weight;
// define methods     public function eat($units) {
echo $this->name." is eating ".$units." units of food... ";
$this->weight += $units;
}
}
?>


在这个实例中,$this前缀指示待修改的变量存在于类的内部(或者,在英语中,“将提供给eat()函数的参数和对象内部的$weight变量相加”)。$this前缀因而提供了一种访问类内部变量和函数的便利方法。下面是关于它如何工作的例子:

<?php
// create instance $baby = new Bear;
$baby->name = "Baby Bear";
$baby->weight = 1000;
// now create another instance
// this one has independent values for each property $brother = new Bear;
$brother->name = "Brother Bear";
$brother->weight = 1000;
// retrieve properties echo $baby->name." weighs ".$baby->weight." units ";
echo $brother->name." weighs ".$brother->weight." units ";
// call eat() $baby->eat(100);
$baby->eat(50);
$brother->eat(11);
// retrieve new values echo $baby->name." now weighs ".$baby->weight." units ";
echo $brother->name." now weighs ".$brother->weight." units ";
?>


上述代码的输出就是:

Baby Bear weighs 1000 units
Brother Bear weighs 1000 units
Baby Bear is eating 100 units of food...
Baby Bear is eating 50 units of food...
Brother Bear is eating 11 units of food...
Baby Bear now weighs 1150 units
Brother Bear now weighs 1011 units


构造器与构造器函数

当调用类来创建新的对象时,自动执行类的一个函数也是可能的。用技客的行话来讲,此被称为构造器,且为了使用它,你的PHP 5类定义必须包含一个特殊的函数:_construct()。

举例而言,如果你想让所有新生的熊是褐色而且体重为100个单位,那么你可以将这些添加到你的类定义中:

<?php
// PHP 5
// class definition class Bear {
// define properties     public $name;
public $weight;
public $age;
public $colour;
// constructor     public function __construct() {
$this->age = ;
$this->weight = 100;
$this->colour = "brown";
}
// define methods }
?>


在PHP 4中,你的构造器必须和类拥有同样的名称。下面为PHP 4写的同样的代码:

<?php
// PHP 4
// class definition class Bear {
// define properties     var $name;
var $weight;
var $age;
var $colour;
// constructor     function Bear() {
$this->age = ;
$this->weight = 100;
$this->colour = "brown";
}
// define methods }
?>


现在,试试创建和使用类的实例:

<?php
// create instance $baby = new Bear;
$baby->name = "Baby Bear";
echo $baby->name." is ".$baby->colour." and weighs ".$baby->weight." units at birth";
?>


这里,构造器在类的对象每次实例化时自动设置缺省属性。因此,当你运行上述脚本时,你会看到下面的结果:

Baby Bear is brown and weighs 100 units at birth


私有的类属性和类方法

正如之前所注释,PHP 5使得将类属性和方法标记为私有是可能的,这就意味着它们不能在类定义之外被操作或者察看。这点对于保护类的内部工作避免被对象实例操作是有帮助的。考虑下面的例子,这些例子通过对Bear()类增加一个新的私有变量$_lastUnitsConsumed而对此进行了解释:

<?php
// PHP 5
// class definition class Bear {
// define properties public $name;
public $age;
public $weight;
private 在PHP中,简单地讲,类是执行一特定任务的程序语句的集合。一个典型的类的定义包含变量和函数两部分,并且充当从中生成该类的特定实例的模板。类的这些特定实例被称为对象。每个对象都有确定的特征或者属性以及确定的预先定义的函数或方法。对象的这些属性和方法直接对应于类定义中的变量和函数。一旦类得到定义,PHP允许你生成你想生成的多个实例。这些实例中的每一个都是具有各自属性及方法的完全独立的对象,而且因此可以独立于其他对象而被操作。这在你需要生成对象的多个实例的情况(例如,两个并发查询的两个并发数据库链接,或者两个购物车)时可以用得着。

类也允许你保持你的代码的模块性(你可以在单独的文件中定义一个类,且仅在你打算使用该类的脚本中包含该文件)和简化代码的更改,因为你只需要编辑一单独的文件来为你所有生成的对象增加新功能即可。

关于“类”的实际例子

为了更好的理解,我们选择一个动物,任何动物都可以。我选择熊,因为我喜欢熊。现在,请问你自己,你能否在OOP的框架下,将这头熊看做是一个“对象”?为什么不呢?毕竟,每只熊都有特定的特征:年龄、体重、性别---这些都相当于对象属性。而且每只熊可以执行特定的活动:吃、睡、走、跑、交配---所有这些都相当于对象方法。

让我们再稍微进一步。因为所有的熊都共享某些特定的特征,所以设想一个Bear()模板是可能的,该模板定义了这个星球上每只熊的基本特征和能力。一旦这个Bear()(“类”)用于创建新的变量$bear(“对象”),那么新创建的熊的个体特征可以独立于其他用这个模板来创建的熊而被操作。

现在,如果你坐下来使用PHP 5编写该类代码,那么它可能会看起来像下面这个样子:

<?php // PHP 5 // class definition class Bear { // define properties public $name; public $weight; public $age; public $sex; public $colour; // define methods public function eat() { echo $this->name." is eating... "; } public function run() { echo $this->name." is running... "; } public function kill() { echo $this->name." is killing prey... "; } public function sleep() { echo $this->name." is sleeping... "; } } ?>


给出这个类后,现在可以很容易地生成和你想要的一样多的熊,然后调整每只熊的个体属性。请看:

<?php
// my first bear
$daddy = new Bear;
// give him a name
$daddy->name = "Daddy Bear";
// how old is he
$daddy->age = 8;
// what sex is he
$daddy->sex = "male";
// what colour is his coat
$daddy->colour = "black";
// how much does he weigh
$daddy->weight = 300;
// give daddy a wife
$mommy = new Bear;
$mommy->name = "Mommy Bear";
$mommy->age = 7;
$mommy->sex = "female";
$mommy->colour = "black";
$mommy->weight = 310;
// and a baby to complete the family
$baby = new Bear;
$baby->name = "Baby Bear";
$baby->age = 1;
$baby->sex = "male";
$baby->colour = "black";
$baby->weight = 180;
// a nice evening in the Bear family
// daddy kills prey and brings it home
$daddy->kill();
// mommy eats it
$mommy->eat();
// and so does baby
$baby->eat();
// mommy sleeps
$mommy->sleep();
// and so does daddy
$daddy->sleep();
// baby eats some more
$baby->eat();
?>


正如上面所展示的解释那样,一旦新的对象被定义,它们的个体方法和属性可以相互独立的被访问和修改。这个会派上用场的,本次教程的剩余部分将会说明这一点。

类定义的本质

既然你已经直接理解了概念,那么让我们看看类定义的本质。

<?php
// PHP 5
// class definition
class Bear {
// define public properties
public $name;
public $age;
// more properties
// define public methods
public function eat() {
echo $this->name." is eating... ";
// more code
}
// more methods
}
?>


每个类定义都以紧跟着类的名字的关键字class开始。你可以给你自己的类任意你可以想像的到的名字,只要它不与PHP中所保留的字相冲突即可。一对大括号包含了所有的类变量和函数,这些类变量和函数被编写,正如你通常对他们编写代码一样。

PHP 5也将可见性概念引入对象模型中。可见性控制了对象属性和方法被调用者操作的程度,且它在定义如何打开和关闭你的类中起着重要的作用。存在着三个层次的可见性,范围从最可见的到最不可见的:公开的、私有的和保护的。在类的定义中,你可以通过在属性或者方法之前使用关键字(public、private或protected)之一来标记其可见性。

缺省情况下,类方法和属性是公开的;这允许调用脚本以触及到对象实例内部,然后直接操作这些对象实例。如果你不喜欢这种侵入的思想,那么你可根据你想对对象内部构件放弃多少控制来将某个属性或方法标记为私有的或者保护的(简言之,不止这些)。

因为PHP 4对象模型不包含对可见性的支持,所以上述类定义将无法在PHP 4中实现。相反,你将需要使用下列的方法:

<?php
// PHP 4
// class definition
class Bear {
// define properties
var $name;
var $weight;
var $age;
var $sex;
var $colour;
// define methods
function eat() {
echo $this->name." is eating... ";
}
function run() {
echo $this->name." is running... ";
}
function kill() {
echo $this->name." is killing prey... ";
}
function sleep() {
echo $this->name." is sleeping... ";
}
}
?>


从上面可以看出,PHP 4中的类属性和方法总是公开的。而且,你对此无能为力!

为了创建类的一个新实例,你可以使用关键字new将新创建的对象赋值给一个PHP变量。

<?php
$daddy = new Bear;
?>


在英语中,上述代码的含义是:创建类Bear()的一个新对象,然后将其赋值给变量$daddy。

现在你可以通过这个变量来访问类的所有方法和属性。比如,下列代码:

<?php
$daddy->name = "Daddy Bear";
?>


其含义是:“将值Daddy Bear赋给类Bear()的特定实例的变量$name”。 再来看下面:

<?php
$daddy->sleep();
?>


上述语句的含义是:“执行类Bear()的特定实例的sleep()函数”。

请注意:->符号用于将对象连接到它们的属性或者方法,以及该事实:当访问一个类实例的属性时符号$被忽略了。

如何访问类变量和类函数

倘若你需要在类定义自身的内部访问它的函数或者变量,那么PHP 4和PHP 5均提供了$this关键字,该$this关键字用于指向“本“类。为了明白这个是如何工作的,让我们改变eat()方法以接受食物单元,然后将其加到熊的体重上。

<?php
// PHP 5
// class definition class Bear {
// define properties     public $name;
public $weight;
// define methods     public function eat($units) {
echo $this->name." is eating ".$units." units of food... ";
$this->weight += $units;
}
}
?>


在这个实例中,$this前缀指示待修改的变量存在于类的内部(或者,在英语中,“将提供给eat()函数的参数和对象内部的$weight变量相加”)。$this前缀因而提供了一种访问类内部变量和函数的便利方法。下面是关于它如何工作的例子:

<?php
// create instance $baby = new Bear;
$baby->name = "Baby Bear";
$baby->weight = 1000;
// now create another instance
// this one has independent values for each property $brother = new Bear;
$brother->name = "Brother Bear";
$brother->weight = 1000;
// retrieve properties echo $baby->name." weighs ".$baby->weight." units ";
echo $brother->name." weighs ".$brother->weight." units ";
// call eat() $baby->eat(100);
$baby->eat(50);
$brother->eat(11);
// retrieve new values echo $baby->name." now weighs ".$baby->weight." units ";
echo $brother->name." now weighs ".$brother->weight." units ";
?>


上述代码的输出就是:

Baby Bear weighs 1000 units
Brother Bear weighs 1000 units
Baby Bear is eating 100 units of food...
Baby Bear is eating 50 units of food...
Brother Bear is eating 11 units of food...
Baby Bear now weighs 1150 units
Brother Bear now weighs 1011 units


构造器与构造器函数

当调用类来创建新的对象时,自动执行类的一个函数也是可能的。用技客的行话来讲,此被称为构造器,且为了使用它,你的PHP 5类定义必须包含一个特殊的函数:_construct()。

举例而言,如果你想让所有新生的熊是褐色而且体重为100个单位,那么你可以将这些添加到你的类定义中:

<?php
// PHP 5
// class definition class Bear {
// define properties     public $name;
public $weight;
public $age;
public $colour;
// constructor     public function __construct() {
$this->age = ;
$this->weight = 100;
$this->colour = "brown";
}
// define methods }
?>


在PHP 4中,你的构造器必须和类拥有同样的名称。下面为PHP 4写的同样的代码:

<?php
// PHP 4
// class definition class Bear {
// define properties     var $name;
var $weight;
var $age;
var $colour;
// constructor     function Bear() {
$this->age = ;
$this->weight = 100;
$this->colour = "brown";
}
// define methods }
?>


现在,试试创建和使用类的实例:

<?php
// create instance $baby = new Bear;
$baby->name = "Baby Bear";
echo $baby->name." is ".$baby->colour." and weighs ".$baby->weight." units at birth";
?>


这里,构造器在类的对象每次实例化时自动设置缺省属性。因此,当你运行上述脚本时,你会看到下面的结果:

Baby Bear is brown and weighs 100 units at birth


私有的类属性和类方法

正如之前所注释,PHP 5使得将类属性和方法标记为私有是可能的,这就意味着它们不能在类定义之外被操作或者察看。这点对于保护类的内部工作避免被对象实例操作是有帮助的。考虑下面的例子,这些例子通过对Bear()类增加一个新的私有变量$_lastUnitsConsumed而对此进行了解释:

___FCKpd___14


现在,既然$_lastUnitsConsumed变量被声明为私有,那么从对象实例对它进行修改的任意企图都会失败,下面是一个例子:

<?php
$bob = new Bear;
$bob->name = "Bobby Bear";
$bob->eat(100);
$bob->eat(200);
echo $bob->getLastMeal();
// the next line will generate a fatal error $bob->_lastUnitsConsumed = 1000;
?>


类方法也可以类似的方式被标记为私有,你自己可以试验一下然后看看结果。

父类与子类

无论是在PHP 4还是在PHP 5中,OOP两个最好的特点就是可扩展性和继承。非常简单,这意味着你可以在现有的类的基础上创建一新类,给它增加新的特征(读取:属性和方法),然后在该新类的基础上创建对象。这些对象将会包含原始父类的所有特征,以及子类的新特征。

作为解释说明,考虑下面的PolarBear()类,该PolarBear()类用新方法扩展了Bear()类。

<?php
// PHP 5
// class definition class Bear {
// define properties     public $name;
public $weight;
public $age;
public $sex;
public $colour;
// constructor     public function __construct() {
$this->age = ;
$this->weight = 100;
}
// define methods     public function eat($units) {
echo $this->name." is eating ".$units." units of food... ";
$this->weight += $units;
}
public function run() {
echo $this->name." is running... ";
}
public function kill() {
echo $this->name." is killing prey... ";
}
public function sleep() {
echo $this->name." is sleeping... ";
}
}
// extended class definition class PolarBear extends Bear {
// constructor     public function __construct() {
parent::__construct();
$this->colour = "white";
$this->weight = 600;
}
// define methods     public function swim() {
echo $this->name." is swimming... ";
}
}
?>


扩展关键字用于将父类扩展为子类。父类所有的函数和变量对于子类而言立即变得可用。这一点在下列代码段中清晰可见:

<?php
// create instance of Bear() $tom = new Bear;
$tom->name = "Tommy Bear";
// create instance of PolarBear() $bob = new PolarBear;
$bob->name = "Bobby Bear";
// $bob can use all the methods of Bear() and PolarBear() $bob->run();
$bob->kill();
$bob->swim();
// $tom can use all the methods of Bear() but not PolarBear() $tom->run();
$tom->kill();
$tom->swim();
?>


在该实例中,对$tom->swim()的最后调用将失败从而引起一个错误,因为Bear()类没有包含swim()方法。然而,对$bob->run()或$bob->kill()的调用没有一个失败的,这是因为作为Bear()类的子类,PolarBear()继承了其父类的所有方法和属性。

请注意,父类构造器是如何在PolarBear()子类构造器中被调用的,这样做是一个好主意,其目的在于当子类实例化时父类的所有必须的初始化得到了执行。然后子类特定的初始化可以在子类构造器中完成。只在子类没有构造器时,父类的构造器才会被自动调用。

你也可以在PHP 4中这样做。下面是PolarBear类定义的PHP 4 版本。

<?php
// PHP 4
// extended class definition class PolarBear extends Bear {
// constructor     function PolarBear() {
parent::Bear();
$this->colour = "white";
$this->weight = 600;
}
// define methods     function swim() {
echo $this->name." is swimming... ";
}
}
?>


为了防止类或其方法被继承,请在类或者方法的名字前使用关键字final(这是PHP 5中的新特征,无法在PHP的先前版本中实现)。下面是一个使得Bear()类不可继承(如果那确实是一个单词的话)的例子:

<?php
// PHP 5
// class definition final class Bear {
// define properties
// define methods }
// extended class definition
// this will fail because Bear() cannot be extended class PolarBear extends Bear {
// define methods }
// create instance of PolarBear()
// this will fail because Bear() could not be extended $bob = new PolarBear;
$bob->name = "Bobby Bear";
echo $bob->weight;
?>


析构器

就像存在构造器一样,因此析构器也是存在的。析构器是一种对象方法,当对内存中的一个对象的最后引用被销毁时调用该对象方法,且它们通常被分派了清理工作的任务(例如,关闭数据库连接或者文件,销毁一个会话等等)。析构器仅在PHP 5中可用,而且必须被命名为__destruct()。下面是一个对其进行说明的例子:

<?php
// PHP 5
// class definition class Bear {
// define properties     public $name;
public $weight;
public $age;
public $sex;
public $colour;
// constructor     public function __construct() {
$this->age = ;
$this->weight = 100;
$this->colour = "brown";
}
// destructor     public function __destruct() {
echo $this->name." is dead. He was ".$this->age."
years old and ".$this->weight." units heavy. Rest in peace! ";
}
// define methods     public function eat($units) {
echo $this->name." is eating ".$units." units of food... ";
$this->weight += $units;
}
public function run() {
echo $this->name." is running... ";
}
public function kill() {
echo $this->name." is killing prey... ";
}
}
// create instance of Bear() $daddy = new Bear;
$daddy->name = "Daddy Bear";
$daddy->age = 10;
$daddy->kill();
$daddy->eat(2000);
$daddy->run();
$daddy->eat(100);
?>


这里,一旦脚本执行结束,对于变量$daddy的引用就不再存在了,因此,析构器将被自动调用。程序的输出就像下面这样:

Daddy Bear is killing prey...
Daddy Bear is eating 2000 units of food...
Daddy Bear is running...
Daddy Bear is eating 100 units of food...
Daddy Bear is dead. He was 10 years old and 2200 units heavy. Rest in peace!


关于类的函数

PHP 4和PHP5提供了一系列函数,该等函数经设计用来让你发现对象属性和方法,以及发现一个对象属于哪一个类。前两个这样的函数是get_class()和get_parent_class()函数,这两个函数告诉你产生特定对象的类的名称。考虑下面的类定义:

<?php
// PHP 5
// base class class Bear {
public $name;
public $weight;
// constructor     public function __construct() {
}
// define methods     public function eat() {
}
public function run() {
}
public function sleep() {
}
}
// derived class class GrizzlyBear extends Bear {
public function kill() {
}
}
?>


然后现在考虑下面的脚本,该脚本使用get_class()与get_parent_class()函数从一个实例得到类的名称:

<?php
$joe = new GrizzlyBear;
$joe->name = "Joe Bear";
$joe->weight = 1000;
echo "Class: " . get_class($joe);
echo "Parent class: " . get_parent_class(get_class($joe));
?>


你可以使用get_class_vars()函数来查看一个类所公开的所有属性,而且用get_class_methods()函数来得到一个类公开的所有方法。为了查看特定对象实例的属性,可以使用get_object_vars()函数而不是get_class_vars()函数,下面是一个对其解释的例子:

<?php
// create instance $joe = new GrizzlyBear;
$joe->name = "Joe Bear";
$joe->weight = 1000;
// get class name $className = get_class($joe);
// get class properties echo "Class properties: ";
print_r(get_class_vars($className));
// get class methods echo " Class methods: ";
print_r(get_class_methods($className));
// get this instance's properties echo " Instance properties: ";
print_r(get_object_vars($joe));
?>


下面是一些样本输出:

Class properties:
Array
(
[name] =>
[weight] =>
)
Class methods:
Array
(
[] => kill
[] => __construct
[] => eat
[] => run
[] => sleep
)
Instance properties:
Array
(
[name] => Joe Bear
[weight] => 1000
)


正如该章程的之前的章节之一所注释那样,print_r函数允许你仔细查看包括对象的任意PHP变量。它非常有用,所以请记录下来以备以后参考。

真实世界中的例子

既然你已经知道了PHP中的对象是如何工作的基础内容,那么让我们以一个真实世界中的例子对此进行总结。考虑下面的userAuth()类,其提供了使用加密密码文件(诸如,/etc/password或htaccess,这两者都用于Unix系统(亦即,互联网的大部分)中)来验证用户登录的方法。我在这里会假定密码文件中的密码采用MD5算法加密,然后使用以$1$开头的12位字符:

<?php
// PHP 5
// class definition class userAuth {
// define properties public $username;
private $passwd;
private $passwdFile;
private 在PHP中,简单地讲,类是执行一特定任务的程序语句的集合。一个典型的类的定义包含变量和函数两部分,并且充当从中生成该类的特定实例的模板。类的这些特定实例被称为对象。每个对象都有确定的特征或者属性以及确定的预先定义的函数或方法。对象的这些属性和方法直接对应于类定义中的变量和函数。一旦类得到定义,PHP允许你生成你想生成的多个实例。这些实例中的每一个都是具有各自属性及方法的完全独立的对象,而且因此可以独立于其他对象而被操作。这在你需要生成对象的多个实例的情况(例如,两个并发查询的两个并发数据库链接,或者两个购物车)时可以用得着。

类也允许你保持你的代码的模块性(你可以在单独的文件中定义一个类,且仅在你打算使用该类的脚本中包含该文件)和简化代码的更改,因为你只需要编辑一单独的文件来为你所有生成的对象增加新功能即可。

关于“类”的实际例子

为了更好的理解,我们选择一个动物,任何动物都可以。我选择熊,因为我喜欢熊。现在,请问你自己,你能否在OOP的框架下,将这头熊看做是一个“对象”?为什么不呢?毕竟,每只熊都有特定的特征:年龄、体重、性别---这些都相当于对象属性。而且每只熊可以执行特定的活动:吃、睡、走、跑、交配---所有这些都相当于对象方法。

让我们再稍微进一步。因为所有的熊都共享某些特定的特征,所以设想一个Bear()模板是可能的,该模板定义了这个星球上每只熊的基本特征和能力。一旦这个Bear()(“类”)用于创建新的变量$bear(“对象”),那么新创建的熊的个体特征可以独立于其他用这个模板来创建的熊而被操作。

现在,如果你坐下来使用PHP 5编写该类代码,那么它可能会看起来像下面这个样子:

<?php // PHP 5 // class definition class Bear { // define properties public $name; public $weight; public $age; public $sex; public $colour; // define methods public function eat() { echo $this->name." is eating... "; } public function run() { echo $this->name." is running... "; } public function kill() { echo $this->name." is killing prey... "; } public function sleep() { echo $this->name." is sleeping... "; } } ?>


给出这个类后,现在可以很容易地生成和你想要的一样多的熊,然后调整每只熊的个体属性。请看:

<?php
// my first bear
$daddy = new Bear;
// give him a name
$daddy->name = "Daddy Bear";
// how old is he
$daddy->age = 8;
// what sex is he
$daddy->sex = "male";
// what colour is his coat
$daddy->colour = "black";
// how much does he weigh
$daddy->weight = 300;
// give daddy a wife
$mommy = new Bear;
$mommy->name = "Mommy Bear";
$mommy->age = 7;
$mommy->sex = "female";
$mommy->colour = "black";
$mommy->weight = 310;
// and a baby to complete the family
$baby = new Bear;
$baby->name = "Baby Bear";
$baby->age = 1;
$baby->sex = "male";
$baby->colour = "black";
$baby->weight = 180;
// a nice evening in the Bear family
// daddy kills prey and brings it home
$daddy->kill();
// mommy eats it
$mommy->eat();
// and so does baby
$baby->eat();
// mommy sleeps
$mommy->sleep();
// and so does daddy
$daddy->sleep();
// baby eats some more
$baby->eat();
?>


正如上面所展示的解释那样,一旦新的对象被定义,它们的个体方法和属性可以相互独立的被访问和修改。这个会派上用场的,本次教程的剩余部分将会说明这一点。

类定义的本质

既然你已经直接理解了概念,那么让我们看看类定义的本质。

<?php
// PHP 5
// class definition
class Bear {
// define public properties
public $name;
public $age;
// more properties
// define public methods
public function eat() {
echo $this->name." is eating... ";
// more code
}
// more methods
}
?>


每个类定义都以紧跟着类的名字的关键字class开始。你可以给你自己的类任意你可以想像的到的名字,只要它不与PHP中所保留的字相冲突即可。一对大括号包含了所有的类变量和函数,这些类变量和函数被编写,正如你通常对他们编写代码一样。

PHP 5也将可见性概念引入对象模型中。可见性控制了对象属性和方法被调用者操作的程度,且它在定义如何打开和关闭你的类中起着重要的作用。存在着三个层次的可见性,范围从最可见的到最不可见的:公开的、私有的和保护的。在类的定义中,你可以通过在属性或者方法之前使用关键字(public、private或protected)之一来标记其可见性。

缺省情况下,类方法和属性是公开的;这允许调用脚本以触及到对象实例内部,然后直接操作这些对象实例。如果你不喜欢这种侵入的思想,那么你可根据你想对对象内部构件放弃多少控制来将某个属性或方法标记为私有的或者保护的(简言之,不止这些)。

因为PHP 4对象模型不包含对可见性的支持,所以上述类定义将无法在PHP 4中实现。相反,你将需要使用下列的方法:

<?php
// PHP 4
// class definition
class Bear {
// define properties
var $name;
var $weight;
var $age;
var $sex;
var $colour;
// define methods
function eat() {
echo $this->name." is eating... ";
}
function run() {
echo $this->name." is running... ";
}
function kill() {
echo $this->name." is killing prey... ";
}
function sleep() {
echo $this->name." is sleeping... ";
}
}
?>


从上面可以看出,PHP 4中的类属性和方法总是公开的。而且,你对此无能为力!

为了创建类的一个新实例,你可以使用关键字new将新创建的对象赋值给一个PHP变量。

<?php
$daddy = new Bear;
?>


在英语中,上述代码的含义是:创建类Bear()的一个新对象,然后将其赋值给变量$daddy。

现在你可以通过这个变量来访问类的所有方法和属性。比如,下列代码:

<?php
$daddy->name = "Daddy Bear";
?>


其含义是:“将值Daddy Bear赋给类Bear()的特定实例的变量$name”。 再来看下面:

<?php
$daddy->sleep();
?>


上述语句的含义是:“执行类Bear()的特定实例的sleep()函数”。

请注意:->符号用于将对象连接到它们的属性或者方法,以及该事实:当访问一个类实例的属性时符号$被忽略了。

如何访问类变量和类函数

倘若你需要在类定义自身的内部访问它的函数或者变量,那么PHP 4和PHP 5均提供了$this关键字,该$this关键字用于指向“本“类。为了明白这个是如何工作的,让我们改变eat()方法以接受食物单元,然后将其加到熊的体重上。

<?php
// PHP 5
// class definition class Bear {
// define properties     public $name;
public $weight;
// define methods     public function eat($units) {
echo $this->name." is eating ".$units." units of food... ";
$this->weight += $units;
}
}
?>


在这个实例中,$this前缀指示待修改的变量存在于类的内部(或者,在英语中,“将提供给eat()函数的参数和对象内部的$weight变量相加”)。$this前缀因而提供了一种访问类内部变量和函数的便利方法。下面是关于它如何工作的例子:

<?php
// create instance $baby = new Bear;
$baby->name = "Baby Bear";
$baby->weight = 1000;
// now create another instance
// this one has independent values for each property $brother = new Bear;
$brother->name = "Brother Bear";
$brother->weight = 1000;
// retrieve properties echo $baby->name." weighs ".$baby->weight." units ";
echo $brother->name." weighs ".$brother->weight." units ";
// call eat() $baby->eat(100);
$baby->eat(50);
$brother->eat(11);
// retrieve new values echo $baby->name." now weighs ".$baby->weight." units ";
echo $brother->name." now weighs ".$brother->weight." units ";
?>


上述代码的输出就是:

Baby Bear weighs 1000 units
Brother Bear weighs 1000 units
Baby Bear is eating 100 units of food...
Baby Bear is eating 50 units of food...
Brother Bear is eating 11 units of food...
Baby Bear now weighs 1150 units
Brother Bear now weighs 1011 units


构造器与构造器函数

当调用类来创建新的对象时,自动执行类的一个函数也是可能的。用技客的行话来讲,此被称为构造器,且为了使用它,你的PHP 5类定义必须包含一个特殊的函数:_construct()。

举例而言,如果你想让所有新生的熊是褐色而且体重为100个单位,那么你可以将这些添加到你的类定义中:

<?php
// PHP 5
// class definition class Bear {
// define properties     public $name;
public $weight;
public $age;
public $colour;
// constructor     public function __construct() {
$this->age = ;
$this->weight = 100;
$this->colour = "brown";
}
// define methods }
?>


在PHP 4中,你的构造器必须和类拥有同样的名称。下面为PHP 4写的同样的代码:

<?php
// PHP 4
// class definition class Bear {
// define properties     var $name;
var $weight;
var $age;
var $colour;
// constructor     function Bear() {
$this->age = ;
$this->weight = 100;
$this->colour = "brown";
}
// define methods }
?>


现在,试试创建和使用类的实例:

<?php
// create instance $baby = new Bear;
$baby->name = "Baby Bear";
echo $baby->name." is ".$baby->colour." and weighs ".$baby->weight." units at birth";
?>


这里,构造器在类的对象每次实例化时自动设置缺省属性。因此,当你运行上述脚本时,你会看到下面的结果:

Baby Bear is brown and weighs 100 units at birth


私有的类属性和类方法

正如之前所注释,PHP 5使得将类属性和方法标记为私有是可能的,这就意味着它们不能在类定义之外被操作或者察看。这点对于保护类的内部工作避免被对象实例操作是有帮助的。考虑下面的例子,这些例子通过对Bear()类增加一个新的私有变量$_lastUnitsConsumed而对此进行了解释:

<?php
// PHP 5
// class definition class Bear {
// define properties public $name;
public $age;
public $weight;
private 在PHP中,简单地讲,类是执行一特定任务的程序语句的集合。一个典型的类的定义包含变量和函数两部分,并且充当从中生成该类的特定实例的模板。类的这些特定实例被称为对象。每个对象都有确定的特征或者属性以及确定的预先定义的函数或方法。对象的这些属性和方法直接对应于类定义中的变量和函数。一旦类得到定义,PHP允许你生成你想生成的多个实例。这些实例中的每一个都是具有各自属性及方法的完全独立的对象,而且因此可以独立于其他对象而被操作。这在你需要生成对象的多个实例的情况(例如,两个并发查询的两个并发数据库链接,或者两个购物车)时可以用得着。

类也允许你保持你的代码的模块性(你可以在单独的文件中定义一个类,且仅在你打算使用该类的脚本中包含该文件)和简化代码的更改,因为你只需要编辑一单独的文件来为你所有生成的对象增加新功能即可。

关于“类”的实际例子

为了更好的理解,我们选择一个动物,任何动物都可以。我选择熊,因为我喜欢熊。现在,请问你自己,你能否在OOP的框架下,将这头熊看做是一个“对象”?为什么不呢?毕竟,每只熊都有特定的特征:年龄、体重、性别---这些都相当于对象属性。而且每只熊可以执行特定的活动:吃、睡、走、跑、交配---所有这些都相当于对象方法。

让我们再稍微进一步。因为所有的熊都共享某些特定的特征,所以设想一个Bear()模板是可能的,该模板定义了这个星球上每只熊的基本特征和能力。一旦这个Bear()(“类”)用于创建新的变量$bear(“对象”),那么新创建的熊的个体特征可以独立于其他用这个模板来创建的熊而被操作。

现在,如果你坐下来使用PHP 5编写该类代码,那么它可能会看起来像下面这个样子:

<?php // PHP 5 // class definition class Bear { // define properties public $name; public $weight; public $age; public $sex; public $colour; // define methods public function eat() { echo $this->name." is eating... "; } public function run() { echo $this->name." is running... "; } public function kill() { echo $this->name." is killing prey... "; } public function sleep() { echo $this->name." is sleeping... "; } } ?>


给出这个类后,现在可以很容易地生成和你想要的一样多的熊,然后调整每只熊的个体属性。请看:

<?php
// my first bear
$daddy = new Bear;
// give him a name
$daddy->name = "Daddy Bear";
// how old is he
$daddy->age = 8;
// what sex is he
$daddy->sex = "male";
// what colour is his coat
$daddy->colour = "black";
// how much does he weigh
$daddy->weight = 300;
// give daddy a wife
$mommy = new Bear;
$mommy->name = "Mommy Bear";
$mommy->age = 7;
$mommy->sex = "female";
$mommy->colour = "black";
$mommy->weight = 310;
// and a baby to complete the family
$baby = new Bear;
$baby->name = "Baby Bear";
$baby->age = 1;
$baby->sex = "male";
$baby->colour = "black";
$baby->weight = 180;
// a nice evening in the Bear family
// daddy kills prey and brings it home
$daddy->kill();
// mommy eats it
$mommy->eat();
// and so does baby
$baby->eat();
// mommy sleeps
$mommy->sleep();
// and so does daddy
$daddy->sleep();
// baby eats some more
$baby->eat();
?>


正如上面所展示的解释那样,一旦新的对象被定义,它们的个体方法和属性可以相互独立的被访问和修改。这个会派上用场的,本次教程的剩余部分将会说明这一点。

类定义的本质

既然你已经直接理解了概念,那么让我们看看类定义的本质。

<?php
// PHP 5
// class definition
class Bear {
// define public properties
public $name;
public $age;
// more properties
// define public methods
public function eat() {
echo $this->name." is eating... ";
// more code
}
// more methods
}
?>


每个类定义都以紧跟着类的名字的关键字class开始。你可以给你自己的类任意你可以想像的到的名字,只要它不与PHP中所保留的字相冲突即可。一对大括号包含了所有的类变量和函数,这些类变量和函数被编写,正如你通常对他们编写代码一样。

PHP 5也将可见性概念引入对象模型中。可见性控制了对象属性和方法被调用者操作的程度,且它在定义如何打开和关闭你的类中起着重要的作用。存在着三个层次的可见性,范围从最可见的到最不可见的:公开的、私有的和保护的。在类的定义中,你可以通过在属性或者方法之前使用关键字(public、private或protected)之一来标记其可见性。

缺省情况下,类方法和属性是公开的;这允许调用脚本以触及到对象实例内部,然后直接操作这些对象实例。如果你不喜欢这种侵入的思想,那么你可根据你想对对象内部构件放弃多少控制来将某个属性或方法标记为私有的或者保护的(简言之,不止这些)。

因为PHP 4对象模型不包含对可见性的支持,所以上述类定义将无法在PHP 4中实现。相反,你将需要使用下列的方法:

<?php
// PHP 4
// class definition
class Bear {
// define properties
var $name;
var $weight;
var $age;
var $sex;
var $colour;
// define methods
function eat() {
echo $this->name." is eating... ";
}
function run() {
echo $this->name." is running... ";
}
function kill() {
echo $this->name." is killing prey... ";
}
function sleep() {
echo $this->name." is sleeping... ";
}
}
?>


从上面可以看出,PHP 4中的类属性和方法总是公开的。而且,你对此无能为力!

为了创建类的一个新实例,你可以使用关键字new将新创建的对象赋值给一个PHP变量。

<?php
$daddy = new Bear;
?>


在英语中,上述代码的含义是:创建类Bear()的一个新对象,然后将其赋值给变量$daddy。

现在你可以通过这个变量来访问类的所有方法和属性。比如,下列代码:

<?php
$daddy->name = "Daddy Bear";
?>


其含义是:“将值Daddy Bear赋给类Bear()的特定实例的变量$name”。 再来看下面:

<?php
$daddy->sleep();
?>


上述语句的含义是:“执行类Bear()的特定实例的sleep()函数”。

请注意:->符号用于将对象连接到它们的属性或者方法,以及该事实:当访问一个类实例的属性时符号$被忽略了。

如何访问类变量和类函数

倘若你需要在类定义自身的内部访问它的函数或者变量,那么PHP 4和PHP 5均提供了$this关键字,该$this关键字用于指向“本“类。为了明白这个是如何工作的,让我们改变eat()方法以接受食物单元,然后将其加到熊的体重上。

<?php
// PHP 5
// class definition class Bear {
// define properties     public $name;
public $weight;
// define methods     public function eat($units) {
echo $this->name." is eating ".$units." units of food... ";
$this->weight += $units;
}
}
?>


在这个实例中,$this前缀指示待修改的变量存在于类的内部(或者,在英语中,“将提供给eat()函数的参数和对象内部的$weight变量相加”)。$this前缀因而提供了一种访问类内部变量和函数的便利方法。下面是关于它如何工作的例子:

<?php
// create instance $baby = new Bear;
$baby->name = "Baby Bear";
$baby->weight = 1000;
// now create another instance
// this one has independent values for each property $brother = new Bear;
$brother->name = "Brother Bear";
$brother->weight = 1000;
// retrieve properties echo $baby->name." weighs ".$baby->weight." units ";
echo $brother->name." weighs ".$brother->weight." units ";
// call eat() $baby->eat(100);
$baby->eat(50);
$brother->eat(11);
// retrieve new values echo $baby->name." now weighs ".$baby->weight." units ";
echo $brother->name." now weighs ".$brother->weight." units ";
?>


上述代码的输出就是:

Baby Bear weighs 1000 units
Brother Bear weighs 1000 units
Baby Bear is eating 100 units of food...
Baby Bear is eating 50 units of food...
Brother Bear is eating 11 units of food...
Baby Bear now weighs 1150 units
Brother Bear now weighs 1011 units


构造器与构造器函数

当调用类来创建新的对象时,自动执行类的一个函数也是可能的。用技客的行话来讲,此被称为构造器,且为了使用它,你的PHP 5类定义必须包含一个特殊的函数:_construct()。

举例而言,如果你想让所有新生的熊是褐色而且体重为100个单位,那么你可以将这些添加到你的类定义中:

<?php
// PHP 5
// class definition class Bear {
// define properties     public $name;
public $weight;
public $age;
public $colour;
// constructor     public function __construct() {
$this->age = ;
$this->weight = 100;
$this->colour = "brown";
}
// define methods }
?>


在PHP 4中,你的构造器必须和类拥有同样的名称。下面为PHP 4写的同样的代码:

<?php
// PHP 4
// class definition class Bear {
// define properties     var $name;
var $weight;
var $age;
var $colour;
// constructor     function Bear() {
$this->age = ;
$this->weight = 100;
$this->colour = "brown";
}
// define methods }
?>


现在,试试创建和使用类的实例:

<?php
// create instance $baby = new Bear;
$baby->name = "Baby Bear";
echo $baby->name." is ".$baby->colour." and weighs ".$baby->weight." units at birth";
?>


这里,构造器在类的对象每次实例化时自动设置缺省属性。因此,当你运行上述脚本时,你会看到下面的结果:

Baby Bear is brown and weighs 100 units at birth


私有的类属性和类方法

正如之前所注释,PHP 5使得将类属性和方法标记为私有是可能的,这就意味着它们不能在类定义之外被操作或者察看。这点对于保护类的内部工作避免被对象实例操作是有帮助的。考虑下面的例子,这些例子通过对Bear()类增加一个新的私有变量$_lastUnitsConsumed而对此进行了解释:

___FCKpd___14


现在,既然$_lastUnitsConsumed变量被声明为私有,那么从对象实例对它进行修改的任意企图都会失败,下面是一个例子:

<?php
$bob = new Bear;
$bob->name = "Bobby Bear";
$bob->eat(100);
$bob->eat(200);
echo $bob->getLastMeal();
// the next line will generate a fatal error $bob->_lastUnitsConsumed = 1000;
?>


类方法也可以类似的方式被标记为私有,你自己可以试验一下然后看看结果。

父类与子类

无论是在PHP 4还是在PHP 5中,OOP两个最好的特点就是可扩展性和继承。非常简单,这意味着你可以在现有的类的基础上创建一新类,给它增加新的特征(读取:属性和方法),然后在该新类的基础上创建对象。这些对象将会包含原始父类的所有特征,以及子类的新特征。

作为解释说明,考虑下面的PolarBear()类,该PolarBear()类用新方法扩展了Bear()类。

<?php
// PHP 5
// class definition class Bear {
// define properties     public $name;
public $weight;
public $age;
public $sex;
public $colour;
// constructor     public function __construct() {
$this->age = ;
$this->weight = 100;
}
// define methods     public function eat($units) {
echo $this->name." is eating ".$units." units of food... ";
$this->weight += $units;
}
public function run() {
echo $this->name." is running... ";
}
public function kill() {
echo $this->name." is killing prey... ";
}
public function sleep() {
echo $this->name." is sleeping... ";
}
}
// extended class definition class PolarBear extends Bear {
// constructor     public function __construct() {
parent::__construct();
$this->colour = "white";
$this->weight = 600;
}
// define methods     public function swim() {
echo $this->name." is swimming... ";
}
}
?>


扩展关键字用于将父类扩展为子类。父类所有的函数和变量对于子类而言立即变得可用。这一点在下列代码段中清晰可见:

<?php
// create instance of Bear() $tom = new Bear;
$tom->name = "Tommy Bear";
// create instance of PolarBear() $bob = new PolarBear;
$bob->name = "Bobby Bear";
// $bob can use all the methods of Bear() and PolarBear() $bob->run();
$bob->kill();
$bob->swim();
// $tom can use all the methods of Bear() but not PolarBear() $tom->run();
$tom->kill();
$tom->swim();
?>


在该实例中,对$tom->swim()的最后调用将失败从而引起一个错误,因为Bear()类没有包含swim()方法。然而,对$bob->run()或$bob->kill()的调用没有一个失败的,这是因为作为Bear()类的子类,PolarBear()继承了其父类的所有方法和属性。

请注意,父类构造器是如何在PolarBear()子类构造器中被调用的,这样做是一个好主意,其目的在于当子类实例化时父类的所有必须的初始化得到了执行。然后子类特定的初始化可以在子类构造器中完成。只在子类没有构造器时,父类的构造器才会被自动调用。

你也可以在PHP 4中这样做。下面是PolarBear类定义的PHP 4 版本。

<?php
// PHP 4
// extended class definition class PolarBear extends Bear {
// constructor     function PolarBear() {
parent::Bear();
$this->colour = "white";
$this->weight = 600;
}
// define methods     function swim() {
echo $this->name." is swimming... ";
}
}
?>


为了防止类或其方法被继承,请在类或者方法的名字前使用关键字final(这是PHP 5中的新特征,无法在PHP的先前版本中实现)。下面是一个使得Bear()类不可继承(如果那确实是一个单词的话)的例子:

<?php
// PHP 5
// class definition final class Bear {
// define properties
// define methods }
// extended class definition
// this will fail because Bear() cannot be extended class PolarBear extends Bear {
// define methods }
// create instance of PolarBear()
// this will fail because Bear() could not be extended $bob = new PolarBear;
$bob->name = "Bobby Bear";
echo $bob->weight;
?>


析构器

就像存在构造器一样,因此析构器也是存在的。析构器是一种对象方法,当对内存中的一个对象的最后引用被销毁时调用该对象方法,且它们通常被分派了清理工作的任务(例如,关闭数据库连接或者文件,销毁一个会话等等)。析构器仅在PHP 5中可用,而且必须被命名为__destruct()。下面是一个对其进行说明的例子:

<?php
// PHP 5
// class definition class Bear {
// define properties     public $name;
public $weight;
public $age;
public $sex;
public $colour;
// constructor     public function __construct() {
$this->age = ;
$this->weight = 100;
$this->colour = "brown";
}
// destructor     public function __destruct() {
echo $this->name." is dead. He was ".$this->age."
years old and ".$this->weight." units heavy. Rest in peace! ";
}
// define methods     public function eat($units) {
echo $this->name." is eating ".$units." units of food... ";
$this->weight += $units;
}
public function run() {
echo $this->name." is running... ";
}
public function kill() {
echo $this->name." is killing prey... ";
}
}
// create instance of Bear() $daddy = new Bear;
$daddy->name = "Daddy Bear";
$daddy->age = 10;
$daddy->kill();
$daddy->eat(2000);
$daddy->run();
$daddy->eat(100);
?>


这里,一旦脚本执行结束,对于变量$daddy的引用就不再存在了,因此,析构器将被自动调用。程序的输出就像下面这样:

Daddy Bear is killing prey...
Daddy Bear is eating 2000 units of food...
Daddy Bear is running...
Daddy Bear is eating 100 units of food...
Daddy Bear is dead. He was 10 years old and 2200 units heavy. Rest in peace!


关于类的函数

PHP 4和PHP5提供了一系列函数,该等函数经设计用来让你发现对象属性和方法,以及发现一个对象属于哪一个类。前两个这样的函数是get_class()和get_parent_class()函数,这两个函数告诉你产生特定对象的类的名称。考虑下面的类定义:

<?php
// PHP 5
// base class class Bear {
public $name;
public $weight;
// constructor     public function __construct() {
}
// define methods     public function eat() {
}
public function run() {
}
public function sleep() {
}
}
// derived class class GrizzlyBear extends Bear {
public function kill() {
}
}
?>


然后现在考虑下面的脚本,该脚本使用get_class()与get_parent_class()函数从一个实例得到类的名称:

<?php
$joe = new GrizzlyBear;
$joe->name = "Joe Bear";
$joe->weight = 1000;
echo "Class: " . get_class($joe);
echo "Parent class: " . get_parent_class(get_class($joe));
?>


你可以使用get_class_vars()函数来查看一个类所公开的所有属性,而且用get_class_methods()函数来得到一个类公开的所有方法。为了查看特定对象实例的属性,可以使用get_object_vars()函数而不是get_class_vars()函数,下面是一个对其解释的例子:

<?php
// create instance $joe = new GrizzlyBear;
$joe->name = "Joe Bear";
$joe->weight = 1000;
// get class name $className = get_class($joe);
// get class properties echo "Class properties: ";
print_r(get_class_vars($className));
// get class methods echo " Class methods: ";
print_r(get_class_methods($className));
// get this instance's properties echo " Instance properties: ";
print_r(get_object_vars($joe));
?>


下面是一些样本输出:

Class properties:
Array
(
[name] =>
[weight] =>
)
Class methods:
Array
(
[] => kill
[] => __construct
[] => eat
[] => run
[] => sleep
)
Instance properties:
Array
(
[name] => Joe Bear
[weight] => 1000
)


正如该章程的之前的章节之一所注释那样,print_r函数允许你仔细查看包括对象的任意PHP变量。它非常有用,所以请记录下来以备以后参考。

真实世界中的例子

既然你已经知道了PHP中的对象是如何工作的基础内容,那么让我们以一个真实世界中的例子对此进行总结。考虑下面的userAuth()类,其提供了使用加密密码文件(诸如,/etc/password或htaccess,这两者都用于Unix系统(亦即,互联网的大部分)中)来验证用户登录的方法。我在这里会假定密码文件中的密码采用MD5算法加密,然后使用以$1$开头的12位字符:

___FCKpd___26


通过前面几页中的例子,这例子中的大部分对你来说应该是清楚的。如果你还不清楚,那么下列脚本将帮助你理解正在发生的:

<?php
// create instance $ua = new userAuth("joe", "secret");
// set password file $ua->setPasswdFile("passwd.txt");
// perform authentication $ua->authenticateUser();
// check result code and display message switch ($ua->getResultCode()) {
case -:
echo "Could not find your user account";
break;
case :
echo "Your password was incorrect";
break;
case :
echo "Welcome, ".$ua->username;
break;
}
?>


这里,用户名和密码被传递给对象的构造器,包含认证凭证的文件名称和路径也同样传递给对象的构造器。authenticateUser()方法负责解析密码文件,然后检查用户是否存在以及密码是否正确。取决于它所发现的结果而产生一个结果码并且将其保存在私有变量$_resultCode中。这个变量可以通过getResultCode()方法来读取,然后显示一条适当的信息。因为整个验证都整洁地封装在一个类中,所以我可以带他到任何地方,在任何脚本中对其进行使用(甚至在其他应用软件中),而且对它进行扩展以支持不同类型的认证模式和容器。

你还可以对对象做更多的操作,尤其是在PHP 5中;我已经将自己限制在这里,因为我不想让你因为讨论过载、抽象类和静态方法而太困惑

lastUnitsConsumed;
// constructor public function __construct() {
$this->age = ;
$this->weight = 100;
$this->_lastUnitsConsumed = ;
}
// define methods public function eat($units) {
echo $this->name." is eating ".$units." units of food... ";
$this->weight += $units;
$this->_lastUnitsConsumed = $units;
}
public function getLastMeal() {
echo "Units consumed in last meal were ".$this->_lastUnitsConsumed." ";
}
}
?>

现在,既然$_lastUnitsConsumed变量被声明为私有,那么从对象实例对它进行修改的任意企图都会失败,下面是一个例子:

___FCKpd___15


类方法也可以类似的方式被标记为私有,你自己可以试验一下然后看看结果。

父类与子类

无论是在PHP 4还是在PHP 5中,OOP两个最好的特点就是可扩展性和继承。非常简单,这意味着你可以在现有的类的基础上创建一新类,给它增加新的特征(读取:属性和方法),然后在该新类的基础上创建对象。这些对象将会包含原始父类的所有特征,以及子类的新特征。

作为解释说明,考虑下面的PolarBear()类,该PolarBear()类用新方法扩展了Bear()类。

___FCKpd___16


扩展关键字用于将父类扩展为子类。父类所有的函数和变量对于子类而言立即变得可用。这一点在下列代码段中清晰可见:

___FCKpd___17


在该实例中,对$tom->swim()的最后调用将失败从而引起一个错误,因为Bear()类没有包含swim()方法。然而,对$bob->run()或$bob->kill()的调用没有一个失败的,这是因为作为Bear()类的子类,PolarBear()继承了其父类的所有方法和属性。

请注意,父类构造器是如何在PolarBear()子类构造器中被调用的,这样做是一个好主意,其目的在于当子类实例化时父类的所有必须的初始化得到了执行。然后子类特定的初始化可以在子类构造器中完成。只在子类没有构造器时,父类的构造器才会被自动调用。

你也可以在PHP 4中这样做。下面是PolarBear类定义的PHP 4 版本。

___FCKpd___18


为了防止类或其方法被继承,请在类或者方法的名字前使用关键字final(这是PHP 5中的新特征,无法在PHP的先前版本中实现)。下面是一个使得Bear()类不可继承(如果那确实是一个单词的话)的例子:

___FCKpd___19


析构器

就像存在构造器一样,因此析构器也是存在的。析构器是一种对象方法,当对内存中的一个对象的最后引用被销毁时调用该对象方法,且它们通常被分派了清理工作的任务(例如,关闭数据库连接或者文件,销毁一个会话等等)。析构器仅在PHP 5中可用,而且必须被命名为__destruct()。下面是一个对其进行说明的例子:

___FCKpd___20


这里,一旦脚本执行结束,对于变量$daddy的引用就不再存在了,因此,析构器将被自动调用。程序的输出就像下面这样:

___FCKpd___21


关于类的函数

PHP 4和PHP5提供了一系列函数,该等函数经设计用来让你发现对象属性和方法,以及发现一个对象属于哪一个类。前两个这样的函数是get_class()和get_parent_class()函数,这两个函数告诉你产生特定对象的类的名称。考虑下面的类定义:

___FCKpd___22


然后现在考虑下面的脚本,该脚本使用get_class()与get_parent_class()函数从一个实例得到类的名称:

___FCKpd___23


你可以使用get_class_vars()函数来查看一个类所公开的所有属性,而且用get_class_methods()函数来得到一个类公开的所有方法。为了查看特定对象实例的属性,可以使用get_object_vars()函数而不是get_class_vars()函数,下面是一个对其解释的例子:

___FCKpd___24


下面是一些样本输出:

___FCKpd___25


正如该章程的之前的章节之一所注释那样,print_r函数允许你仔细查看包括对象的任意PHP变量。它非常有用,所以请记录下来以备以后参考。

真实世界中的例子

既然你已经知道了PHP中的对象是如何工作的基础内容,那么让我们以一个真实世界中的例子对此进行总结。考虑下面的userAuth()类,其提供了使用加密密码文件(诸如,/etc/password或htaccess,这两者都用于Unix系统(亦即,互联网的大部分)中)来验证用户登录的方法。我在这里会假定密码文件中的密码采用MD5算法加密,然后使用以$1$开头的12位字符:

___FCKpd___26


通过前面几页中的例子,这例子中的大部分对你来说应该是清楚的。如果你还不清楚,那么下列脚本将帮助你理解正在发生的:

___FCKpd___27


这里,用户名和密码被传递给对象的构造器,包含认证凭证的文件名称和路径也同样传递给对象的构造器。authenticateUser()方法负责解析密码文件,然后检查用户是否存在以及密码是否正确。取决于它所发现的结果而产生一个结果码并且将其保存在私有变量$_resultCode中。这个变量可以通过getResultCode()方法来读取,然后显示一条适当的信息。因为整个验证都整洁地封装在一个类中,所以我可以带他到任何地方,在任何脚本中对其进行使用(甚至在其他应用软件中),而且对它进行扩展以支持不同类型的认证模式和容器。

你还可以对对象做更多的操作,尤其是在PHP 5中;我已经将自己限制在这里,因为我不想让你因为讨论过载、抽象类和静态方法而太困惑

resultCode;
// constructor
// must be passed username and password public function __construct($username, $password) {
$this->username = $username;
$this->passwd = $password;
$this->_resultCode = -;
}
// used to set file to read for password data public function setPasswdFile($file) {
$this->passwdFile = $file;
}
// returns: -1 if user does not exist
// 0 if user exists but password is incorrect
// 1 if username and password are correct public function getResultCode() {
return $this->_resultCode;
}
public function authenticateUser() {
// make sure that the script has permission to read this file! $data = file($this->passwdFile);
// iterate through file foreach ($data as $line) {
$arr = explode(":", $line);
// if username matches
// test password if ($arr[] == $this->username) {
// if match, user/pass combination is correct
// return 1 if ($arr[] == crypt($this->passwd, $arr[])) {
$this->_resultCode = ;
break;
}
// otherwise return 0 else {
$this->_resultCode = ;
break;
}
}
}
}
// end class definition }
?>

通过前面几页中的例子,这例子中的大部分对你来说应该是清楚的。如果你还不清楚,那么下列脚本将帮助你理解正在发生的:

___FCKpd___27


这里,用户名和密码被传递给对象的构造器,包含认证凭证的文件名称和路径也同样传递给对象的构造器。authenticateUser()方法负责解析密码文件,然后检查用户是否存在以及密码是否正确。取决于它所发现的结果而产生一个结果码并且将其保存在私有变量$_resultCode中。这个变量可以通过getResultCode()方法来读取,然后显示一条适当的信息。因为整个验证都整洁地封装在一个类中,所以我可以带他到任何地方,在任何脚本中对其进行使用(甚至在其他应用软件中),而且对它进行扩展以支持不同类型的认证模式和容器。

你还可以对对象做更多的操作,尤其是在PHP 5中;我已经将自己限制在这里,因为我不想让你因为讨论过载、抽象类和静态方法而太困惑

lastUnitsConsumed;
// constructor public function __construct() {
$this->age = ;
$this->weight = 100;
$this->_lastUnitsConsumed = ;
}
// define methods public function eat($units) {
echo $this->name." is eating ".$units." units of food... ";
$this->weight += $units;
$this->_lastUnitsConsumed = $units;
}
public function getLastMeal() {
echo "Units consumed in last meal were ".$this->_lastUnitsConsumed." ";
}
}
?>

现在,既然$_lastUnitsConsumed变量被声明为私有,那么从对象实例对它进行修改的任意企图都会失败,下面是一个例子:

___FCKpd___15


类方法也可以类似的方式被标记为私有,你自己可以试验一下然后看看结果。

父类与子类

无论是在PHP 4还是在PHP 5中,OOP两个最好的特点就是可扩展性和继承。非常简单,这意味着你可以在现有的类的基础上创建一新类,给它增加新的特征(读取:属性和方法),然后在该新类的基础上创建对象。这些对象将会包含原始父类的所有特征,以及子类的新特征。

作为解释说明,考虑下面的PolarBear()类,该PolarBear()类用新方法扩展了Bear()类。

___FCKpd___16


扩展关键字用于将父类扩展为子类。父类所有的函数和变量对于子类而言立即变得可用。这一点在下列代码段中清晰可见:

___FCKpd___17


在该实例中,对$tom->swim()的最后调用将失败从而引起一个错误,因为Bear()类没有包含swim()方法。然而,对$bob->run()或$bob->kill()的调用没有一个失败的,这是因为作为Bear()类的子类,PolarBear()继承了其父类的所有方法和属性。

请注意,父类构造器是如何在PolarBear()子类构造器中被调用的,这样做是一个好主意,其目的在于当子类实例化时父类的所有必须的初始化得到了执行。然后子类特定的初始化可以在子类构造器中完成。只在子类没有构造器时,父类的构造器才会被自动调用。

你也可以在PHP 4中这样做。下面是PolarBear类定义的PHP 4 版本。

___FCKpd___18


为了防止类或其方法被继承,请在类或者方法的名字前使用关键字final(这是PHP 5中的新特征,无法在PHP的先前版本中实现)。下面是一个使得Bear()类不可继承(如果那确实是一个单词的话)的例子:

___FCKpd___19


析构器

就像存在构造器一样,因此析构器也是存在的。析构器是一种对象方法,当对内存中的一个对象的最后引用被销毁时调用该对象方法,且它们通常被分派了清理工作的任务(例如,关闭数据库连接或者文件,销毁一个会话等等)。析构器仅在PHP 5中可用,而且必须被命名为__destruct()。下面是一个对其进行说明的例子:

___FCKpd___20


这里,一旦脚本执行结束,对于变量$daddy的引用就不再存在了,因此,析构器将被自动调用。程序的输出就像下面这样:

___FCKpd___21


关于类的函数

PHP 4和PHP5提供了一系列函数,该等函数经设计用来让你发现对象属性和方法,以及发现一个对象属于哪一个类。前两个这样的函数是get_class()和get_parent_class()函数,这两个函数告诉你产生特定对象的类的名称。考虑下面的类定义:

___FCKpd___22


然后现在考虑下面的脚本,该脚本使用get_class()与get_parent_class()函数从一个实例得到类的名称:

___FCKpd___23


你可以使用get_class_vars()函数来查看一个类所公开的所有属性,而且用get_class_methods()函数来得到一个类公开的所有方法。为了查看特定对象实例的属性,可以使用get_object_vars()函数而不是get_class_vars()函数,下面是一个对其解释的例子:

___FCKpd___24


下面是一些样本输出:

___FCKpd___25


正如该章程的之前的章节之一所注释那样,print_r函数允许你仔细查看包括对象的任意PHP变量。它非常有用,所以请记录下来以备以后参考。

真实世界中的例子

既然你已经知道了PHP中的对象是如何工作的基础内容,那么让我们以一个真实世界中的例子对此进行总结。考虑下面的userAuth()类,其提供了使用加密密码文件(诸如,/etc/password或htaccess,这两者都用于Unix系统(亦即,互联网的大部分)中)来验证用户登录的方法。我在这里会假定密码文件中的密码采用MD5算法加密,然后使用以$1$开头的12位字符:

___FCKpd___26


通过前面几页中的例子,这例子中的大部分对你来说应该是清楚的。如果你还不清楚,那么下列脚本将帮助你理解正在发生的:

___FCKpd___27


这里,用户名和密码被传递给对象的构造器,包含认证凭证的文件名称和路径也同样传递给对象的构造器。authenticateUser()方法负责解析密码文件,然后检查用户是否存在以及密码是否正确。取决于它所发现的结果而产生一个结果码并且将其保存在私有变量$_resultCode中。这个变量可以通过getResultCode()方法来读取,然后显示一条适当的信息。因为整个验证都整洁地封装在一个类中,所以我可以带他到任何地方,在任何脚本中对其进行使用(甚至在其他应用软件中),而且对它进行扩展以支持不同类型的认证模式和容器。

你还可以对对象做更多的操作,尤其是在PHP 5中;我已经将自己限制在这里,因为我不想让你因为讨论过载、抽象类和静态方法而太困惑
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: