我想重新定义一个方法,并调用我祖先的版本,而不是我父母的版本。
这是一个简短的例子:
// This class is autogenerated and I am not supposed to modify it.
class myParent extends myGrandparent {
function doSomething() {
doA();
doB();
doC();
parent::doSomething();
}
}
// Here is my code
class myClass extends myParent {
function doSomething() {
// doA(); // I don't want to do A anymore.
// doB(); // Neither B.
doC(); // But I want to keep doing C.
parent::doSomething(); // OOPS!! This does A and B (and C again)!
}
}
如何直接调用myGrandparent的方法,而不是myParent的?
答案 0 :(得分:4)
我不同意“你不能这样做”这个论点 - 你可以用Reflection做到这一点。
考虑以下类结构:
class A {
function foo() {
echo 'A';
}
}
class B extends A {
function foo() {
parent::foo();
echo 'B';
}
}
class C extends B {
function foo() {
parent::foo();
echo 'C';
}
}
初始化时:
$o = new C;
$o->foo();
将打印(按照预期,见this demo):
ABC
挑战是从输出中删除B
,实际上只执行A
的{{1}}和foo()
的{{1}}。所以,让我们进入Reflection并抓住C
的{{1}}方法,然后在foo()
的对象上调用它。现在考虑A
的替代定义:
foo()
现在,您只能获得输出(如this demo中所示):
C
这是否是“良好做法”,取决于OP。我想我已经证明可以“跳过”C
函数的实现并从孙子类中调用祖父项函数。
答案 1 :(得分:2)
不确定用例是什么,但除非我误解了问题/问题(很可能),否则你可以完全调用任意祖先(公共或受保护)方法,无论它被覆盖了多少次介于两者之间,甚至是任何祖先成员属性(公共或受保护)的默认值,即使这些属性也被覆盖了。例如,使用类层次结构:
爸爸>妈妈>宝贝>婴儿,其中方法 sayWhat()&实例变量 $ el 在每个后代类中被覆盖,您可以调用任何祖先说出来自Infant的什么方法,并访问不同的祖先默认属性值:
class Papa {
protected $el = 'PapaEl';
protected function sayWhat($className = null) {
if (!$className) {
$className = get_class($this);
}
$classVars = get_class_vars($className);
$localEl = $classVars['el'];
echo "<h2>What is PAPA!. El: [$localEl]</h2>";
}
}
class Mama extends Papa {
protected $el = 'MamaEl';
protected function sayWhat() {
echo "<h2>What is MAMA! El: [$this->el]</h2>";
}
}
class Baby extends Mama {
protected $el = 'BabyEl';
protected function sayWhat() {
echo "<h2>What is Lil' Baby!! El: [$this->el]</h2>";
}
}
class Infant extends Baby {
protected $el = 'InfantEl';
protected function sayWhat($className) {
Papa::sayWhat($className);
}
public function mySayWhat($className) {
$this->sayWhat($className);
}
}
$i = new Infant();
$i->mySayWhat('Mama');
输出:
什么是PAPA! El:[MamaEl]
不确定它有什么价值,但如果有人有要求,那似乎非常可行......
答案 2 :(得分:0)
你真的不能。您可能需要直接从myGrandParent扩展,或者您需要在MyParent中重写逻辑以提供对myGrandParents方法的“传递”访问。例如,您可以在myParent上创建一个方法,如下所示:
function doSomethingGrandparent() {
parent::doSomething();
}
然后在myClass中更改你的doSomething方法,如下所示:
function doSomething() {
parent::doSomethingGrandparent();
}
答案 3 :(得分:0)
答案是否定的,你不能。子项重新声明方法的父功能并完全覆盖它。
我认为需要静态方法,因为你不能将parent ::关键字链接到“祖父母”类,因此,parent :: parent :: foo()不起作用。