php - 以编程方式识别覆盖特征方法的方法
问题描述
我正在尝试在覆盖特征方法的类中生成一组方法。这是一个简化的示例,显示了我的应用程序中典型类和特征的方法结构:
class demo
{
public function MethodA()
{
return 'method A from class';
}
public function MethodC()
{
return 'method C from class';
}
public function MethodE()
{
return 'method E from class';
}
use tGeneric;
}
trait tGeneric
{
public function MethodA()
{
return 'method A from trait';
}
public function MethodB()
{
return 'method B from trait';
}
public function MethodD()
{
return 'method D from trait';
}
public function MethodE()
{
return 'method E from trait';
}
}
根据PHP 手册中列出的优先规则:
优先顺序是当前类中的方法会覆盖 Trait 方法,而 Trait 方法又会覆盖基类中的方法。
这是按预期运行的,因为此代码的输出:
$object = new demo();
$array = [
$object->MethodA(),
$object->MethodB(),
$object->MethodC(),
$object->MethodD(),
$object->MethodE()
];
$br = '<br>';
$msg = '';
foreach ($array as $value):
$msg .= $value . $br;
endforeach;
echo $msg . $br;
demo
覆盖特征方法的类中的方法tGeneric
是 MethodA() 和 MethodE()。有没有办法以编程方式在类中生成一个仅包含这些方法的数组,这些方法覆盖特征中的方法?
我已经尝试过反射,但该GetMethods()
方法检索一个类的所有方法,无论它们是源自该类还是通过使用特性获得。
这段代码:
$rc = new ReflectionClass('demo');
$d = $rc->GetMethods();
$traits = class_uses('demo');
foreach ($traits as $trait):
$reflection = new ReflectionClass($trait);
$t = $reflection->GetMethods();
endforeach;
DisplayInfo($d);
DisplayInfo($t);
function DisplayInfo($array)
{
$br = '<br>';
echo '<b>' . $array[0]->class . '</b>' . $br;
foreach ($array as $value):
echo $value->name . $br;
endforeach;
echo $br;
}
解决方案
通过比较,您几乎可以确定方法会覆盖特征方法:
- 他们的文件名 (
ReflectionFunctionAbstract::getFileName
), - 和他们的起跑线 (
ReflectionFunctionAbstract::getStartLine
)
健康)状况
if ($class_method->getFileName() !== $trait_method->getFileName()
|| $class_method->getStartLine() !== $trait_method->getStartLine()) {
$methods_overridden[] = $class_method->getName();
}
(当然,它们也需要具有相同的名称)
全功能
/**
* Given a class name, retrieves the corresponding class' methods that override
* trait methods.
*
* @param string $class_name
* @return \ReflectionMethod[]
* @throws \ReflectionException
*/
function getMethodsOverriddenFromTraits(string $class_name): array
{
$class = new \ReflectionClass($class_name);
// Retrieve trait methods
$trait_methods = [];
foreach ($class->getTraits() as $trait) {
foreach ($trait->getMethods() as $trait_method) {
$trait_methods[$trait_method->getName()] = $trait_method;
}
}
// Compute class methods that override them
$methods_overridden = [];
foreach ($class->getMethods() as $class_method) {
if (array_key_exists($class_method->getName(), $trait_methods)) {
$trait_method = $trait_methods[$class_method->getName()];
if ($class_method->getFileName() !== $trait_method->getFileName()
|| $class_method->getStartLine() !== $trait_method->getStartLine()) {
$methods_overridden[] = $class_method->getName();
}
}
}
return $methods_overridden;
}
推荐阅读
- excel - 需要 Excel 帮助:具有多个表格的文本文件导入
- c# - 模拟问题 - 值不能为空。(参数“来源”)
- reactjs - React/Redux 电子商务状态管理设计问题?
- azure-devops - 通过 Rest Api 将值插入 Azure DevOps 自定义字段
- python - 如何在按不同值排序的列表中打印字典中的值
- geometry - AutoHotKey 点击无法识别 + 圆周运动问题
- sqlite - sqlite-utils convert 函数可以选择两列吗?
- go - Golang kubernetes 客户端 - 使用标签修补现有资源
- r - 为什么 pivot_longer() 在其输出中仅嵌套四个整数值
- laravel - Laravel 8 Livewire 在其他方法中使用来自渲染的变量数据