ZetCode

PHP 接口关键字

最后修改于 2025 年 4 月 16 日

PHP interface 关键字定义了类要实现的契约。接口指定了类必须实现哪些方法,而没有定义如何实现。它们实现了多态性并有助于创建松散耦合的系统。

基本定义

接口是实现类必须定义的方法的蓝图。它只包含方法签名,没有任何实现。接口中的所有方法都隐式为 public 和 abstract。

类使用 implements 关键字实现接口。一个类可以实现多个接口。接口可以使用 extends 关键字扩展其他接口。

语法:interface InterfaceName { public function methodName(); }。接口不能包含属性(常量除外)或方法体。

基本接口实现

此示例演示了一个简单的接口和一个实现它的类。

basic_interface.php
<?php

declare(strict_types=1);

interface Logger {
    public function log(string $message): void;
}

class FileLogger implements Logger {
    public function log(string $message): void {
        file_put_contents('app.log', $message, FILE_APPEND);
    }
}

$logger = new FileLogger();
$logger->log("User logged in\n");

Logger 接口定义了一个必须实现的方法。FileLogger 通过提供方法体来实现此接口。这确保了所有记录器都具有相同的基础功能。代码将消息写入日志文件。

多接口实现

此示例显示了一个类实现多个接口。

multiple_interfaces.php
<?php

declare(strict_types=1);

interface Renderable {
    public function render(): string;
}

interface Cacheable {
    public function cache(): void;
}

class Page implements Renderable, Cacheable {
    public function render(): string {
        return "<h1>Welcome</h1>";
    }
    
    public function cache(): void {
        echo "Page cached\n";
    }
}

$page = new Page();
echo $page->render();
$page->cache();

Page 类实现了 RenderableCacheable 两个接口。它必须为两个接口中的所有方法提供实现。这允许对象具有多个角色。可以在任何需要其中一个接口的地方使用该类。

接口继承

此示例演示了一个接口扩展另一个接口。

interface_inheritance.php
<?php

declare(strict_types=1);

interface Vehicle {
    public function start(): void;
    public function stop(): void;
}

interface Car extends Vehicle {
    public function accelerate(float $speed): void;
}

class Sedan implements Car {
    public function start(): void {
        echo "Engine started\n";
    }
    
    public function stop(): void {
        echo "Engine stopped\n";
    }
    
    public function accelerate(float $speed): void {
        echo "Accelerating to {$speed} km/h\n";
    }
}

$sedan = new Sedan();
$sedan->start();
$sedan->accelerate(60);
$sedan->stop();

Car 接口扩展了 Vehicle,继承了它的方法。Sedan 必须实现这两个接口中的所有方法。这创建了一个契约的层次结构。该类为所有必需的方法提供了具体的实现。

接口常量

此示例展示了如何在接口中定义和使用常量。

interface_constants.php
<?php

declare(strict_types=1);

interface MathOperations {
    const PI = 3.14159;
    
    public function calculateArea(float $radius): float;
}

class Circle implements MathOperations {
    public function calculateArea(float $radius): float {
        return self::PI * $radius * $radius;
    }
}

$circle = new Circle();
echo "Area: " . $circle->calculateArea(5);

接口可以包含实现类可以访问的常量。常量隐式为 public、static 和 final。Circle 类在其面积计算中使用 PI 常量。接口常量提供跨实现的共享值。

使用接口进行类型提示

此示例演示了使用接口进行类型提示。

interface_type_hinting.php
<?php

declare(strict_types=1);

interface Notifier {
    public function send(string $message): void;
}

class EmailNotifier implements Notifier {
    public function send(string $message): void {
        echo "Email sent: {$message}\n";
    }
}

class NotificationService {
    public function __construct(private Notifier $notifier) {}
    
    public function notify(string $message): void {
        $this->notifier->send($message);
    }
}

$service = new NotificationService(new EmailNotifier());
$service->notify("Hello World");

NotificationService 接受任何 Notifier 实现。这允许灵活的依赖注入。服务不需要知道具体的通知器类。这促进了松散耦合和更轻松的测试。

接口 vs 抽象类

此示例比较了接口与抽象类。

interface_vs_abstract.php
<?php

declare(strict_types=1);

// Interface
interface Drawable {
    public function draw(): void;
}

// Abstract class
abstract class Shape {
    protected string $color;
    
    public function __construct(string $color) {
        $this->color = $color;
    }
    
    abstract public function getArea(): float;
}

// Concrete class implementing both
class Circle extends Shape implements Drawable {
    private float $radius;
    
    public function __construct(string $color, float $radius) {
        parent::__construct($color);
        $this->radius = $radius;
    }
    
    public function draw(): void {
        echo "Drawing a {$this->color} circle\n";
    }
    
    public function getArea(): float {
        return pi() * $this->radius * $this->radius;
    }
}

$circle = new Circle("red", 5);
$circle->draw();
echo "Area: " . $circle->getArea();

接口定义契约,而抽象类可以提供部分实现。一个类可以扩展一个抽象类,但实现多个接口。Circle 继承自 Shape 并实现了 Drawable。这展示了如何结合这两种方法。

现代 PHP:接口特性

此示例演示了现代 PHP 接口特性。

modern_interface.php
<?php

declare(strict_types=1);

// Interface with return type declaration
interface Calculator {
    public function add(float $a, float $b): float;
    
    // Default implementation (PHP 8.0+)
    public function subtract(float $a, float $b): float {
        return $a - $b;
    }
}

class BasicCalculator implements Calculator {
    public function add(float $a, float $b): float {
        return $a + $b;
    }
}

$calc = new BasicCalculator();
echo "5 + 3 = " . $calc->add(5, 3) . "\n";
echo "5 - 3 = " . $calc->subtract(5, 3) . "\n";

PHP 8.0 引入了接口中的默认方法实现。该示例显示了返回类型声明和一个默认方法。类可以覆盖默认方法。这在接口设计中提供了更大的灵活性。BasicCalculator 仅实现了 add 方法。

最佳实践

来源

PHP 接口文档

本教程通过实际示例介绍了 PHP 接口,展示了基本用法、多重实现、继承和现代特性。

作者

我叫 Jan Bodnar,是一位充满激情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。到目前为止,我撰写了 1,400 多篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

列出 所有 PHP 教程