【问题标题】:php check if method overridden in child classphp 检查子类中的方法是否被覆盖
【发布时间】:2013-07-13 20:16:56
【问题描述】:

是否可以检查一个方法是否被 PHP 中的子类覆盖?

<!-- language: lang-php -->

class foo {
    protected $url;
    protected $name;
    protected $id;

    var $baz;

    function __construct($name, $id, $url) {
        $this->name = $name;
        $this->id = $id;
        $this->url = $url;
    }

    function createTable($data) {
        // do default actions
    }
}

儿童班:

class bar extends foo {
    public $goo;

    public function createTable($data) {
        // different code here
    }
}

当遍历定义为此类成员的对象数组时,如何检查哪些对象具有新方法而不是旧方法?有method_overridden(mixed $object, string $method name)这样的函数吗?

foreach ($objects as $ob) {
    if (method_overridden($ob, "createTable")) {
        // stuff that should only happen if this method is overridden
    }
    $ob->createTable($dataset);
}

我知道template method pattern,但是假设我希望程序的控制与类和方法本身分开。我需要一个像method_overridden 这样的函数来完成这个。

【问题讨论】:

  • 重载,还是被覆盖?我以为 PHP 没有方法重载
  • 我的意思是被覆盖了,是的
  • 如果您的设计依赖于了解类如何覆盖特定方法,那么您的设计就存在严重问题。 OO 背后的整个想法是,您可以向对象发送消息,并由对象以适当的方式处理它。调用代码不应该关心正在调用什么实现或如何处理它的消息。

标签: php oop overloading


【解决方案1】:

检查声明的类是否与对象的类匹配:

$reflector = new \ReflectionMethod($ob, 'createTable');
$isProto = ($reflector->getDeclaringClass()->getName() !== get_class($ob));

PHP 手册链接:

【讨论】:

  • 这当然是我想要的方式,但我有一个问题:你为什么在 ReflectionMethod 之前使用命名空间运算符?是否要确保从全局命名空间调用该方法,而不是意外调用在更局部范围内定义的同名方法?
  • 您的情况可能不需要它。如果上面的代码位于命名空间下,则需要导入 ReflectionMethod 类,或者使用全局命名空间前缀 (`\`) 访问它。我只是确保这种情况得到处理:)
  • 这也可以通过类属性来完成。只需改用\ReflectionProperty()
【解决方案2】:

要获取此信息,您必须使用 ReflectionClass。您可以尝试 getMethod 并检查方法的类名。

$class = new ReflectionClass($this);
$method = $class->getMethod("yourMethod");
if ($method->class == 'classname') {
    //.. do something
}

但是请记住,反射不是很快,所以要小心使用。

【讨论】:

  • 在 PHP 5.5.20 中,$method['class'] 给了我:不能使用 ReflectionMethod 类型的对象作为数组$method-&gt;class 工作得很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-29
  • 2021-12-15
相关资源
最近更新 更多