PHP implements 关键字
最后修改于 2025 年 4 月 16 日
PHP implements 关键字用于在面向对象编程中实现接口。 它创建一个类必须遵循的契约。 接口定义方法签名,但不提供实现。 使用 implements 的类必须提供具体的方法实现。
基本定义
接口是实现类必须定义的方法的蓝图。 implements 关键字表明一个类将履行接口的契约。 接口可以包含方法签名和常量。
与类不同,接口不能包含属性定义或方法体。 接口中的所有方法都隐式为 public。 一个类可以实现多个接口,用逗号分隔。
语法:class ClassName implements InterfaceName { ... }。 实现类必须定义接口中声明的所有方法。 否则会导致致命错误。
基本接口实现
此示例演示了一个带有一个方法的基本接口实现。
<?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 类实现此接口并提供具体的方法。 该类必须与接口的方法签名完全匹配。
实现多个接口
此示例展示了一个类同时实现多个接口。
<?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 接口。 它必须为两个接口中的所有方法提供实现。 多个接口用逗号分隔。
接口继承
此示例演示一个接口扩展另一个接口。
<?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 并且必须提供 eat 和 breathe 方法。 接口继承创建了契约的层次结构。
带有常量的接口
此示例展示了一个接口定义常量,实现类可以使用这些常量。
<?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 并且不能被覆盖。
使用接口进行类型提示
此示例演示了在函数参数中使用接口进行类型提示。
<?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 接口的对象。 这允许不同的缓存实现可以互换使用。 使用接口进行类型提示可以实现多态。
实现接口的抽象类
此示例展示了一个抽象类部分实现一个接口。
<?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 完成实现。 抽象类可以提供部分接口实现。
用于依赖注入的接口
此示例演示了使用接口进行依赖注入。
<?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 接口,而不是具体的实现。 这使得可以轻松交换支付提供商。 接口可以在组件之间实现松耦合。
最佳实践
- 命名: 使用以 "able" 结尾的描述性名称(例如,Loggable)。
- 单一责任: 保持接口专注于一种能力。
- 文档: 清楚地记录接口的目的和用法。
- 分离: 遵循接口分离原则 (ISP)。
- 测试: 模拟接口以简化单元测试。
来源
本教程通过实际示例介绍了 PHP 接口实现,展示了 implements 关键字在各种情况下的用法。
作者
列出 所有 PHP 教程。