(PHP 8)
PHP 注解为类、方法、函数、参数、属性和常量提供了结构化且机器可读的元数据。它们可以通过反射 API 在运行时进行检查,从而实现动态行为而无需修改代码。注解提供了声明式的方式来为代码添加元数据注释。
注解使得功能实现与其使用之间实现解耦。接口通过强制定义方法来规范结构,而注解则为方法、函数、属性和常量在内的多个元素提供元数据。与接口不同,接口强制实现方法,而注解则在不改变代码结构的情况下为其添加注释。
注解可以通过提供元数据而非强制结构来补充或替代可选的接口方法。以表示应用程序中操作的 ActionHandler
接口为例。某些实现可能需要设置步骤,而其他实现则不需要。与其强制所有实现(implementing)ActionHandler 的类都定义
setUp() 方法,不如使用注解来表明设置需求。这种方法提高了灵活性,并允许在必要时多次应用属性。
示例 #1 用注解实现接口的可选方法
<?php
interface ActionHandler
{
public function execute();
}
#[Attribute]
class SetUp {}
class CopyFile implements ActionHandler
{
public string $fileName;
public string $targetDirectory;
#[SetUp]
public function fileExists()
{
if (!file_exists($this->fileName)) {
throw new RuntimeException("File does not exist");
}
}
#[SetUp]
public function targetDirectoryExists()
{
if (!file_exists($this->targetDirectory)) {
mkdir($this->targetDirectory);
} elseif (!is_dir($this->targetDirectory)) {
throw new RuntimeException("Target directory $this->targetDirectory is not a directory");
}
}
public function execute()
{
copy($this->fileName, $this->targetDirectory . '/' . basename($this->fileName));
}
}
function executeAction(ActionHandler $actionHandler)
{
$reflection = new ReflectionObject($actionHandler);
foreach ($reflection->getMethods() as $method) {
$attributes = $method->getAttributes(SetUp::class);
if (count($attributes) > 0) {
$methodName = $method->getName();
$actionHandler->$methodName();
}
}
$actionHandler->execute();
}
$copyAction = new CopyFile();
$copyAction->fileName = "/tmp/foo.jpg";
$copyAction->targetDirectory = "/home/user";
executeAction($copyAction);