PHP 接口

时间:2018-11-15 15:15:48  来源:igfitidea点击:

在本教程中,我们将学习如何使用PHP接口,这是PHP面向对象编程中最重要的构建块之一。

PHP 接口介绍

接口允许您定义一个类必须实现哪些方法。

要定义接口,可以使用interface关键字,如下所示:

<?php
interface IMyInterface{
 // 各种方法
}

接口由尚未实现的方法组成。换句话说,接口的所有方法都是抽象方法。接口可以有自己的常量。语法如下:

<?php
interface IMyInterface{
    const INTERFACE_CONSTANT_1 = 1;
    const INTERFACE_CONSTANT_2 = 'a string';
    
    public function method_1();
    public function method_2();
}

接口中的所有方法都必须是public的。

当我们要声明一个重用了现有类的属性和方法的新类时,我们说子类继承自或扩展了父类。
但是对于接口,我们说一个类实现了一个接口。一个类只能从一个类继承,而一个类可以实现一个或多个接口。

要实现一个接口,可以使用implements操作符:

class MyClass implements IMyInterface{
 public function method_1(){
 // 方法1的实现
 }
 public function method_2(){
 // 方法2的实现
 }
}

当一个类实现一个接口时,我们也称它为一个具体的类。具体类必须实现接口中具有相同名称和参数的所有方法。

一个类不能同时实现两个具有相同方法名称的接口,因为这样会导致调用的方法不确定。

与类类似,还可以使用extends操作符来扩展一个接口,如下所示:

interface IReadable{
    public function read();
}
 
interface IWritable extends IReadable{
    public function write();
}

IWritable接口通过添加一个write()抽象方法扩展了IReadable接口。

为什么我们要在PHP中使用接口?

有几个原因:

  • 通过实现接口,对象的调用者只需要关心对象的接口,而不需要关心对象方法的实现。因此,可以在不影响接口调用者的情况下变更具体的实现。
  • 接口允许不相关的类实现同一组方法,而不用管它们在类继承层次结构中的位置如何。
  • 接口使您能够对多重继承进行建模,因为一个类可以实现多个接口,而它只能扩展一个类。

PHP接口示例

在下面的示例中,我们将向您展示如何使用接口使系统变得更易于扩展和更灵活。

假设,我们必须创建一个可以记录消息的日志记录器。

首先,我们将创建一个名为ILogger的接口,如下所示:

<?php
interface ILogger{
 public function log($message);
}

其次,我们可以创建一个FileLogger类,它将日志消息写入日志文件。

<?php

require_once 'ilogger.php';

class FileLogger implements ILogger {

    private $handle;
    private $logFile;

    public function __construct($filename, $mode = 'a') {
        $this->logFile = $filename;
        // 打开用于追加内容的日志文件
        $this->handle = fopen($filename, $mode)
                or die('Could not open the log file');
    }

    public function log($message) {
        $message = date("F j, Y, g:i a") . ': ' . $message . "\n";
        fwrite($this->handle, $message);
    }

    public function __destruct() {
        if ($this->handle) {
            fclose($this->handle);
        }
    }

}

我们可以像下面这样使用FileLogger类:

<?php

require_once 'classes/filelogger.php';

function testFilelogger() {
    $logger = new FileLogger('./log.txt', 'w');
    $logger->log('开始使用文件记录器');
    $logger->log('另一条日志消息');
}

testFilelogger();

然后,我们可以添加一个数据库日志,实现ILogger接口如下:

为了演示,我们将DBLogger类写得尽可能地简化。

<?php
require_once 'ilogger.php';

class DBLogger implements ILogger {
    public function log($message) {
        echo sprintf("记录 %s 到数据库中\n", $message);
    }
}

我们可以很容易地添加实现ILogger接口的其他类型的日志记录器,而不需要修改现有的日志记录器。

下面的代码片段演示了如何同时使用多个使用了同一个ILogger接口的记录器:

<?php

function testLoggers() {
    $loggers = array(
        new FileLogger('./log.txt'),
        new DBLogger()
    );

    foreach ($loggers as $logger) {
        $logger->log('Log message');
    }
}

testLoggers();