在定义一个类时,如果我们使用了abstract关键字,那么,这个类就会被定义为抽象的;抽象类有什么特点呢?很简单,它不能被实例化,也就是不能对象。那么,一个不能被实例化的类有什么用呢?简单的说,它是专用的父类,其唯一的作用就是让其它类来继承它的。
我们先看一下下面的代码。
abstract class ClsA
{
public abstract function work();
}
class ClsB extends ClsA
{
public function work()
{
echo __CLASS__.' is working.';
}
}
obj = new ClsB();obj->work();
我们首先定义了抽象类ClsA,然后,在其子类ClsB中,我们重写了work()方法,其中的CLASS是PHP的内部常量,表示当前类的名称,此代码会显示“ClsB is working.”。这两个类看起来可能并没有什么特别,但是,当我们创建ClsA类的实例时,就会产生错误,如下面的代码。
$obj = new ClsA(); // 错误
再看一下抽象类与抽象方法的定义:
- 定义类时,在class关键字前使用abstract关键字,这个类就会被定义为抽象类,抽象类不能被实例化。
- 定义抽象方法时,应在function关键字前使用abstract关键字,抽象方法没有方法体(即{}定义的代码块),而是直接使用分号(;)作为语句结束。当一个类中定义了一个抽象方法时,那么,这个类就必须定义为抽象类。
此外,我们知道,PHP中类的属性,其本质是变量,但我们是无法定义抽象变量的,所以,如果需要将属性的读、写定义为抽象,可以使用两种方法,一是使用getter和setter方法,如下面的代码。
abstract class ClsA
{
public abstract function getAge();
public abstract function setAge(age);
}
class ClsB extends ClsA
{ privateage;
public function getAge()
{
return this->age; } public function setAge(age)
{
if(is_int(age) &&age>=0 && age<=150)this->age = age; else throw new Exception('ClsB: 年龄应该在0到150之间'); }
}obj = new ClsB();
obj->setAge(35);
echoobj->getAge();
使用getter和setter方法,虽然是在使用方法模拟属性的读写操作,但它可以更精确地指定属性的名称。第二种实现抽象属性的方法就是在类中定义抽象的get()和set()方法,如下面的代码。
abstract class ClsA
{
public abstract function __get(key); public abstract function __set(key, value);
}
class ClsB extends ClsA
{ privatearr = array();
public function __get(key) { returnthis->arr[key]; }
public function __set(key, value) {this->arr[key] =value;
}
}
obj = new ClsB();obj->age = 35;
echo $obj->age;
关于get()和set()方法的特点,我们已经在上一章介绍过了,在实际应用中,我们可以根据实际需要选择具体的实现策略。