我正在尝试在类中生成一组覆盖特征方法的方法。这是一个简化的示例,显示了我的应用程序中典型类和特征的方法结构:
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';
}
}
Run Code Online (Sandbox Code Playgroud)
根据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;
Run Code Online (Sandbox Code Playgroud)
类中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;
}
Run Code Online (Sandbox Code Playgroud)
通过比较,您几乎可以确定某个方法会覆盖特征方法:
ReflectionFunctionAbstract::getFileName),ReflectionFunctionAbstract::getStartLine)if ($class_method->getFileName() !== $trait_method->getFileName()
|| $class_method->getStartLine() !== $trait_method->getStartLine()) {
$methods_overridden[] = $class_method->getName();
}
Run Code Online (Sandbox Code Playgroud)
(当然,他们也需要有相同的名字)
/**
* 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;
}
Run Code Online (Sandbox Code Playgroud)
此处演示: https: //3v4l.org/EcFIC