首页 > 解决方案 > 以编程方式识别覆盖特征方法的方法

问题描述

我正在尝试在覆盖特征方法的类中生成一组方法。这是一个简化的示例,显示了我的应用程序中典型类和特征的方法结构:

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;
}

给出这个输出:
在此处输入图像描述

标签: php

解决方案


通过比较,您几乎可以确定方法会覆盖特征方法:

健康)状况

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;
}

此处演示:https ://3v4l.org/EcFIC


推荐阅读