另一种在PHP 5中加入的信特性就是接口与抽象类。它们的作用是用来创建强制性基于一些设计的类。一个抽象类本质上来说就是定义一个特殊类型整体的骨架——举例来说,可以使用一个抽象类定义一个基本的“车”的概念,拥有两扇车门,一个锁和可以解锁与闭锁的方法。抽象类不能实例化,但是可以被继承,因此继承下来的抽象方法将在子类中进行具体化。例如:
abstract class DataStore_Adapter { private $id; abstract function insert(); abstract function update(); public function save() { if (!is_null($this->id)) { $this->update(); } else { $this->insert(); } } } class PDO_DataStore_Adapter extends DataStore_Adapter { public __construct($dsn) { //... } public insert() { //... } public update() { //... } }
作者提示:类中只要出现抽象方法,则此类必须要声明为abstruct。
如上代码所示,定义了一个Data_Adapter的类,同时定义了两个抽象方法insert()和update()。需要提醒的是,这两个方法都没有身体(Siemen注:也就是没有实现)——这是抽象类的必备条件之一—也就是为什么类本身会被修饰成abstract,其原因就是需要满足解释器语法需要。用PDO_DataStore_Adapter类继承DataStore_Adapter,而其PDO_DataStore_Adapter类实现了insert()与update()也就不再是抽象类了。
6.4.1 接口
另一方面,接口是用来指定API使实现这个接口的类必须实现哪些方法。它能够使得实现了接口的类都具备某一逻辑需求——例如:可是利用接口抽象出数据库连接的公共API,然后编写一系列的类去实现它,来对不同的DBMS进行支持。
接口方法是没有身体的:
interface DataStore_Adapter { public function insert(); public function update(); public function save(); public function newRecord($name = null); } class PDO_DataStore_Adapter implements DataStore_Adapter { public function insert() { //... } public function update() { //... } public function save() { //... } public function newRecord($name = null) { //... } }
假设,上例中,没有把所有的方法都实现或者没有按照接口给出的参数来实现接口方法,就会看到如下显示:
Fatal error: Class PDO_DataStore_Adapter contains 1 abstract method and must therefore be declare abstract or implement the remaining method (DataStore_Adapter::save) in //document// on line 27
or
Fatal error: Declaration of PDO_DataStore_Adapter::newRecord() must be compatible with that of DataStore_Adapter::newRecord() in //document// on line 12
这种情况在类实现多接口上发生的比实现单接口的类中发生的要更多:
class PDO_DataStore_Adapter implements DataStore_Adapter, SeekableInterator { //... }
此例中,我们需要同时实现DataStore_Adapter和SeekableIterator两个接口。另外,一个类只能继承一个父类,但可以实现多个接口:
作者提示:记住——一个类只能继承一个父类,但是可以实现多个接口。
class PDO_DataStore_Adapter extends PDO implements DataStore_Adapter, SeekableIterator { //... }
6.4.2 从对象找类
时常需要确定对象是由哪个类实现出来的,或者是否实现某个接口,而这些,instanceof都可以做到:
if ($obj instanceof MyClass) { echo "\$obj is an instance of MyClass"; }
显然,instanceof允许审查对象实现自哪个类,或者接口。