在PHP应用开发中,使用类主要有以下几种目的:
- 定义一个复杂的数据结构类型,包含了一些数据,以及对这些数据的处理方法;通过这样的封装,我们可以方便、安全地对一系列相关联的数据进行操作。
- 封装代码,对相关功能的代码进行封装,方便调用。
- 模拟枚举,在PHP中并没有定义枚举的功能,不过,我们可以使用一个类来模拟枚举类型的定义。
在PHP中,创建类同样使用class关键字,如下面的代码,我们创建了一个名为CTest的类。
class CTest
{
// 类结构
}
这是一个最简单的类定义,在创建类的成员前,我们还必须要搞清楚一个问题,那就是类成员的可访问性。
类成员的可访问性
在PHP中,定义类成员的可访问性有三种:
- private关键字,成员定义为私有的,它们只能在其所定义类的内部使用。
- public关键字,成员定义为公共的,它们将是类的对外接口,也就是说,使用这些成员来获取或设置类的数据,以及对这些数据执行某些操作。此外,public是类成员的默认可访问性设置。
- protected关键字,成员定义为受保护的,这些成员可以在其所定义的类或其子类中使用。在下一章,“类的继承”中,我们将看到这类成员的使用。
开发中,我们将类的成员定义为哪一种可访问性,需要对类及成员的目的和特点进行综合分析,并作出权衡;对于代码结构的把握,还需要我们从实践中多分析、多思考,并从中得出最合理的定义。
类的实例化(创建对象)
当定义了类以后,我们就可以定义这个类类型的变量,这一过程就称为类的实例化,这个变量称为类的实例,或者是大家更熟悉的“对象”概念。在PHP中,创建一个类的对象使用new关键字,如下面的代码。
$obj = new CTest();
代码中,我定义了obj变量,它被实例化成为CTest类的一个对象。我们使用print_r()函数,可以显示obj的相关信息,如:
print_r($obj); // 显示 CTest Object()
此外,需要注意的是在函数的参数中使用类类型时,我们可以使用具体的类来限制参数的类型,如:
function printCTest(CTest obj)
{ print_r(obj);
}
obj = new CTest();
printCTest(obj);
请注意printCTest()函数的定义,我们指定了参数$obj的类型,调用此函数时,如果带入的参数不是CTest类的对象,则会产生错误。
instanceof运算符
在前面的介绍中,我们介绍过,可以使用is_int()函数来判断一个变量是否为一个整数;那么,对于一个对象,我们如何判断它是不是一个类的实例,过去,我们可以使用is_a()函数来判断,如:
var_dump(is_a($obj, 'CTest'));
此代码会显示bool(true)。
现在,我们可以使用一个含义更清晰的运算符,即instanceof运算符,这也是推荐使用的方法,如下面的代码。
var_dump($obj instanceof CTest);
此代码同样显示bool(true)。
构造函数
构造函数的功能是在创建对象时,对它的数据进行一些初始化工作,现在,我们在PHP的类中定义构造函数时,可以使用__construct()函数。如下面的代码。
class CTest
{
public num; // 构造函数 public function __construct() {this->num = 100;
}
}
在这个CTest类中,我们首先定义了一个公共的(public)变量num,它并没有被赋值;然后,在构造函数中,我们将其赋值为100。
请注意this变量的使用,它特指当前对象。在类的内部,我们总是使用this来引用对象的成员;此时,符号在this前,对象变量num就不需要再使用$符号了。而->符号意思也就是特指访问对象的成员。
下面的代码,我们将观察构造函数是否起作用了。
$obj = new CTest();
echo $obj->num; // 显示 100
我们可以看到,在代码中并没有给$obj->num变量赋值的语句,但是,显示的结果却是100,而这正是构造函数在幕后默默工作的结果,而构造函数正是在new CTest()执行时被自动调用的。
友情提示:__construct()前是两个英文半角下划线,后面介绍的一系列“魔术方法”也是这样。
在定义构造函数时,我们还可以指定参数,而且可以是可选参数,如下面的代码。
class CTest
{
public num; // 构造函数 function __construct(num = 1)
{
this->num =num;
}
}
现在,我们创建一个对象,如下面的代码。
$obj1 = new CTest();
$obj2 = new CTest(99);
echo $obj1->num,'<br>',$obj2->num;
代码会显示1和99,其中obj1对象创建时没有指定参数,则obj1->num的值默认为1,而obj2创建时,指定参数为99,所以obj2->num的值就是99。
析构函数
在对象中,我们可能需要处理很复杂的数据,有时还会使用一些外部的资源,如磁盘文件、数据库等等,在对象中使用后,我们还需要释放这些资源,此时,类的析构函数就可以帮助我们完成这项工作,在PHP的类中,析构函数应定义为__destruct()。如下面的代码。
class CTest
{
// 析构函数
public function __destruct()
{
echo '对象任务已完成';
}
}
obj = new CTest();
unset(obj);
实际上,如果没有unset($obj);语句,代码同样会显示“对象任务已完成”,这是因为PHP有自动回收的功能,当一个对象不再需要时,PHP会自动释放它的内存空间,类的析构函数就是在对象被释放时自动调用的。
我们已经了解了关于类和对象的创建,以及类型检查相关的内容,接下来,我们再来讨论一下类成员的两个主角:属性与方法。