如何在不出现E_STRICT错误的情况下调用祖父母方法?

2022-08-30 22:33:15

有时我需要执行祖父母方法(即绕过父方法),我知道这是代码气味,但有时我无法更改其他类(框架,库等)。

在PHP中,我们可以用这样的东西来做到这一点:

call_user_func(array(get_parent_class(get_parent_class($childObject)), 'grandParentMethod'));

问题是,如果您启用了E_STRICT错误,您将收到如下错误:

严格的标准:非静态方法 GrandParent::grandParentMethod() 不应该在 ...

我只找到了一个解决方案(没有删除E_STRICT),它只是添加以抑制错误。@

但那真的很丑陋,有人知道更好的解决方案吗?

谢谢!PS:我无法实例化如下新对象:

$grandparent = get_parent_class(get_parent_class($son));
$gp= new $grandparent;
$gp->grandParentMethod

因为我需要在$son的上下文中调用我的祖父母方法。


答案 1

您可以直接通过名字称呼祖父母(不需要反射,也不需要)。call_user_func

class Base {
    protected function getFoo() {
        return 'Base';
    }
}

class Child extends Base {
    protected function getFoo() {
        return parent::getFoo() . ' Child';
    }
}

class Grandchild extends Child {
    protected function getFoo() {
        return Base::getFoo() . ' Grandchild';
    }
}

该调用可能看起来像静态调用(由于冒号语法),但事实并非如此。就像不是静态的一样。Base::getFoo::parent::

从类内的继承链调用方法将正确绑定值,将其作为常规方法调用,遵守可见性规则(例如受保护),并且不会违反任何类型的行为!$this

乍一看,这可能看起来有点奇怪,但是,这是在PHP中执行此操作的方法。


答案 2

您可以使用ReflempMethod->invoke()

例:

<?php
class Grandpa {
    protected $age = 'very old';
    public function sayMyAge() {
        return 'sayMyAge() in Grandpa should be very old. ' . 
                  'My age is: ' . $this->age;
    }
}

class Pa extends Grandpa {
    protected $age = 'less old';
    public function sayMyAge() {
        return 'sayMyAge() in Pa should be less old. ' .
                  'My age is: ' . $this->age;
    }
}

class Son extends Pa {
    protected $age = 'younger';
    public function sayMyAge() {
        return 'sayMyAge() in Son should be younger. ' .
                  'My age is: ' . $this->age;
    }
}

$son = new Son();
$reflectionMethod = new ReflectionMethod(get_parent_class(get_parent_class($son)), 
                                         'sayMyAge');
echo $reflectionMethod->invoke($son);
// returns:
// sayMyAge() in Grandpa should be very old. My age is: younger

注意:调用的方法必须是公共的。


推荐