ZetCode

PHP implements 关键字

最后修改于 2025 年 4 月 16 日

PHP implements 关键字用于在面向对象编程中实现接口。 它创建一个类必须遵循的契约。 接口定义方法签名,但不提供实现。 使用 implements 的类必须提供具体的方法实现。

基本定义

接口是实现类必须定义的方法的蓝图。 implements 关键字表明一个类将履行接口的契约。 接口可以包含方法签名和常量。

与类不同,接口不能包含属性定义或方法体。 接口中的所有方法都隐式为 public。 一个类可以实现多个接口,用逗号分隔。

语法:class ClassName implements InterfaceName { ... }。 实现类必须定义接口中声明的所有方法。 否则会导致致命错误。

基本接口实现

此示例演示了一个带有一个方法的基本接口实现。

basic_interface.php
<?php

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("Error: File not found\n");

Logger 接口声明一个 log 方法。 FileLogger 类实现此接口并提供具体的方法。 该类必须与接口的方法签名完全匹配。

实现多个接口

此示例展示了一个类同时实现多个接口。

multiple_interfaces.php
<?php

interface Serializable {
    public function serialize(): string;
}

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

class Widget implements Serializable, Renderable {
    private $data;
    
    public function __construct(array $data) {
        $this->data = $data;
    }
    
    public function serialize(): string {
        return json_encode($this->data);
    }
    
    public function render(): string {
        return implode(', ', $this->data);
    }
}

$widget = new Widget(['a', 'b', 'c']);
echo $widget->serialize();
echo $widget->render();

Widget Serializable 和 Renderable 接口。 它必须为两个接口中的所有方法提供实现。 多个接口用逗号分隔。

接口继承

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

interface_inheritance.php
<?php

interface Animal {
    public function eat(): void;
}

interface Mammal extends Animal {
    public function breathe(): void;
}

class Dog implements Mammal {
    public function eat(): void {
        echo "Dog is eating\n";
    }
    
    public function breathe(): void {
        echo "Dog is breathing\n";
    }
}

$dog = new Dog();
$dog->eat();
$dog->breathe();

Mammal 接口扩展 Animal,继承其方法。 Dog 实现 Mammal 并且必须提供 eatbreathe 方法。 接口继承创建了契约的层次结构。

带有常量的接口

此示例展示了一个接口定义常量,实现类可以使用这些常量。

interface_constants.php
<?php

interface HttpStatus {
    const OK = 200;
    const NOT_FOUND = 404;
    const SERVER_ERROR = 500;
}

class Response implements HttpStatus {
    public function send(int $code): void {
        if ($code === self::OK) {
            echo "Request successful";
        } elseif ($code === self::NOT_FOUND) {
            echo "Resource not found";
        } else {
            echo "Server error";
        }
    }
}

$response = new Response();
$response->send(HttpStatus::OK);

HttpStatus 接口定义状态码常量。 Response 类实现该接口并使用 self:: 访问常量。 接口常量始终是 public 并且不能被覆盖。

使用接口进行类型提示

此示例演示了在函数参数中使用接口进行类型提示。

type_hinting.php
<?php

interface Cache {
    public function get(string $key): ?string;
    public function set(string $key, string $value): void;
}

class RedisCache implements Cache {
    public function get(string $key): ?string {
        // Simulate Redis get
        return "value_for_$key";
    }
    
    public function set(string $key, string $value): void {
        // Simulate Redis set
        echo "Setting $key to $value\n";
    }
}

function storeData(Cache $cache, string $key, string $value): void {
    $cache->set($key, $value);
}

$cache = new RedisCache();
storeData($cache, 'user1', 'John Doe');

storeData 函数接受任何实现 Cache 接口的对象。 这允许不同的缓存实现可以互换使用。 使用接口进行类型提示可以实现多态。

实现接口的抽象类

此示例展示了一个抽象类部分实现一个接口。

abstract_implementation.php
<?php

interface Database {
    public function connect(): void;
    public function query(string $sql): array;
    public function disconnect(): void;
}

abstract class BaseDatabase implements Database {
    protected $connection;
    
    public function connect(): void {
        $this->connection = true;
        echo "Connected\n";
    }
    
    abstract public function query(string $sql): array;
    
    public function disconnect(): void {
        $this->connection = false;
        echo "Disconnected\n";
    }
}

class MySQLDatabase extends BaseDatabase {
    public function query(string $sql): array {
        echo "Executing: $sql\n";
        return ['result1', 'result2'];
    }
}

$db = new MySQLDatabase();
$db->connect();
$db->query("SELECT * FROM users");
$db->disconnect();

BaseDatabase 抽象类实现了 Database,但将 query 留为抽象。 具体类 MySQLDatabase 完成实现。 抽象类可以提供部分接口实现。

用于依赖注入的接口

此示例演示了使用接口进行依赖注入。

dependency_injection.php
<?php

interface PaymentGateway {
    public function charge(float $amount): bool;
}

class StripeGateway implements PaymentGateway {
    public function charge(float $amount): bool {
        echo "Charging \$$amount with Stripe\n";
        return true;
    }
}

class PayPalGateway implements PaymentGateway {
    public function charge(float $amount): bool {
        echo "Charging \$$amount with PayPal\n";
        return true;
    }
}

class OrderProcessor {
    private $gateway;
    
    public function __construct(PaymentGateway $gateway) {
        $this->gateway = $gateway;
    }
    
    public function process(float $amount): bool {
        return $this->gateway->charge($amount);
    }
}

$processor = new OrderProcessor(new StripeGateway());
$processor->process(100.50);

OrderProcessor 依赖于 PaymentGateway 接口,而不是具体的实现。 这使得可以轻松交换支付提供商。 接口可以在组件之间实现松耦合。

最佳实践

来源

PHP 接口文档

本教程通过实际示例介绍了 PHP 接口实现,展示了 implements 关键字在各种情况下的用法。

作者

我叫 Jan Bodnar,是一位充满激情的程序员,拥有丰富的编程经验。 我从 2007 年开始撰写编程文章。 迄今为止,我撰写了 1,400 多篇文章和 8 本电子书。 我拥有十多年的编程教学经验。

列出 所有 PHP 教程