ZetCode

PHP final 关键字

最后修改于 2025 年 4 月 16 日

PHP 的 final 关键字用于限制面向对象编程中的继承和方法重写。 当应用于一个类时,它阻止该类被扩展。 当应用于一个方法时,它阻止该方法在子类中被重写。

基本定义

final 关键字可以应用于类和方法。 final 类不能被任何其他类继承。 final 方法不能被任何子类重写。

Final 类通常用于安全或设计原因,当您希望确保某些功能无法被修改时。 Final 方法用于当您希望在所有子类中保留原始实现时。

语法:对于类,使用 final class ClassName {},对于方法,使用 final public function methodName() {}。 final 关键字放在类或方法声明之前。

Final 类示例

此示例演示如何创建无法被扩展的 final 类。

final_class.php
<?php

declare(strict_types=1);

final class DatabaseConnection {
    public function connect(): void {
        echo "Connecting to database...";
    }
}

// This will cause a fatal error
// class MySQLConnection extends DatabaseConnection {}

DatabaseConnection 类被声明为 final,因此任何扩展它的尝试都将导致致命错误。 这确保了类的实现保持不变。 Final 类通常用于关键的系统组件。

Final 方法示例

此示例展示了如何创建一个无法被重写的 final 方法。

final_method.php
<?php

declare(strict_types=1);

class PaymentProcessor {
    final public function processPayment(float $amount): void {
        echo "Processing payment of {$amount}";
    }
}

class CreditCardProcessor extends PaymentProcessor {
    // This will cause a fatal error
    // public function processPayment(float $amount): void {}
}

processPayment 方法在父类中被声明为 final。 任何在子类中重写它的尝试都将导致错误。 这保留了原始的支付处理逻辑。 其他非 final 方法仍然可以被重写。

Final 类与 Final 方法

此示例结合了 final 类和 final 方法的概念。

final_class_method.php
<?php

declare(strict_types=1);

final class MathOperations {
    final public static function add(int $a, int $b): int {
        return $a + $b;
    }
    
    final public static function multiply(int $a, int $b): int {
        return $a * $b;
    }
}

echo MathOperations::add(5, 3); // Outputs 8

MathOperations 类是 final 的,并且包含 final static 方法。 这创建了一个实用类,该类不能被扩展或修改。 所有方法都必须完全按照实现使用。 这对于数学运算很常见。

在继承链中使用 Final

此示例展示了 final 方法在多级继承链中的工作方式。

inheritance_chain.php
<?php

declare(strict_types=1);

class Vehicle {
    final public function startEngine(): void {
        echo "Engine started";
    }
}

class Car extends Vehicle {
    // Can't override startEngine()
    public function drive(): void {
        $this->startEngine();
        echo "Car is moving";
    }
}

class SportsCar extends Car {
    // Can't override startEngine() here either
}

startEngine 方法在 Vehicle 类中是 final 的。 这阻止了任何子类或孙子类重写它。 该方法仍然可以正常调用。 这确保了一致的引擎启动行为。

与抽象类结合使用 Final

此示例演示了在抽象类中使用 final 方法。

abstract_final.php
<?php

declare(strict_types=1);

abstract class Logger {
    final public function log(string $message): void {
        $this->writeToLog($this->formatMessage($message));
    }
    
    abstract protected function writeToLog(string $message): void;
    
    final protected function formatMessage(string $message): string {
        return date('Y-m-d H:i:s') . " - " . $message;
    }
}

class FileLogger extends Logger {
    protected function writeToLog(string $message): void {
        file_put_contents('app.log', $message, FILE_APPEND);
    }
    
    // Can't override formatMessage()
}

抽象 Logger 类有一个 final log 方法,该方法调用抽象和 final protected 方法。 子类必须实现抽象方法,但不能修改 final 方法。 这创建了一个灵活但受控的日志记录框架。

在接口实现中使用 Final

此示例展示了在实现接口时 final 的工作方式。

interface_final.php
<?php

declare(strict_types=1);

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

final class RedisCache implements CacheInterface {
    final public function get(string $key): ?string {
        // Redis implementation
        return "Value for {$key}";
    }
    
    final public function set(string $key, string $value): void {
        // Redis implementation
        echo "Setting {$key} to {$value}";
    }
}

RedisCache 类是 final 的,并实现一个接口。 它的方法也是 final 的,这使其成为一个完整、不可修改的实现。 当您希望强制执行特定的缓存实现时,此模式非常有用。 接口方法不能在接口本身中声明为 final。

Final 类与构造函数

此示例演示了一个带有 final 构造函数的 final 类。

final_constructor.php
<?php

declare(strict_types=1);

final class Configuration {
    private array $settings;
    
    final public function __construct(array $settings) {
        $this->settings = $settings;
    }
    
    final public function get(string $key): mixed {
        return $this->settings[$key] ?? null;
    }
}

$config = new Configuration(['debug' => true]);
echo $config->get('debug') ? 'Debug on' : 'Debug off';

Configuration 类是 final 的,并且有一个 final 构造函数。 这确保了配置加载机制无法修改。 该类提供对设置的只读访问。 这是配置管理的一种常见安全模式。

最佳实践

来源

PHP final 关键字文档

本教程涵盖了 PHP final 关键字,并提供了实际示例,展示了如何在各种情况下阻止继承和方法重写。

作者

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

列出 所有 PHP 教程