2011-11-25 84 views
4

在PHP中,我试图从对象的父类继承的方法引用对象的父类中定义的方法。下面的代码:如何从继承的方法中调用PHP父方法?

class base_class { 
    function do_something() { 
    print "base_class::do_something()\n"; 
    } 
    function inherit_this() { 
    parent::do_something(); 
    } 
} 
class middle_class extends base_class { 
    function do_something() { 
    print "middle_class::do_something()\n"; 
    } 
} 
class top_class extends middle_class { 
    function do_something() { 
    print "top_class::do_something()\n"; 
    $this->inherit_this(); 
    } 
} 

$obj = new top_class; 
$obj->do_something(); 

的问题是,家长::在inherit_this do_something()()试图找到父类BASE_CLASS的,对象的实际类的不是父母,和上面的例子中抛出一个错误。有什么我可以写,而不是调用middle_class :: do_something()的parent :: do_something(),即使在扩展(比如说)top_class的类中也可以工作吗?

+0

你不能使用php5,然后做一个私有的base_class方法吗?这意味着继承类不能覆盖该方法。 – smack0007

+0

也许,但我实际上是想让interiting类重写方法。这实际上是原始代码的大部分重点。我可能需要重写这个例子,但它会更长。 –

回答

1

我首先对grrbrr404说“谢谢”。他给了我一些想法,让我开始朝着正确的方向发展。

我终于解决该解决方案是以下几点:

function inherit_this() { 
    $bt = debug_backtrace(); 
    call_user_func(array($this, get_parent_class($bt[1]['class']) . '::do_something')); 
} 

这不是漂亮(我特别讨厌呼吁debug_backtrace()此),但它一直设置到这个$对象上下文,并处理情况该方法从对象层次结构中间的某个方法调用。

对于那些发现我的例子令人困惑和/或想知道“为什么你想要这样做?”我很抱歉,并提供了下面的附加例子,这有希望更具说明性,更接近原始问题。这是相当长的时间,但希望说明为什么我关心保持$这个设置正确,也说明了为什么我不能硬编码任何特定的类名或使用$ this-> method()。避免无限循环始终是我的首要任务。 :-)

class class1_required_type { } 
class class2_required_type { } 
class class3_required_type { } 
class class4_required_type { } 

class class1 { 
    protected $data = array(); 
    protected function checkType($name, $value, $requiredType) { 
    print "In class1::checkType()\n"; 
    if (get_class($value) === $requiredType) { 
     $backtrace = debug_backtrace(); 
     call_user_func(array($this, get_parent_class($backtrace[1]['class']) . "::mySet"), $name, $value); 
    } else { 
     throw new Exception(get_class($this) . "::mySet('" . $name . "') requires an object of type '" . $requiredType . "', but got '" . get_class($value) . "'"); 
    } 
    } 
    function mySet($name, $value) { 
    print "In class1::mySet()\n"; 
    if ($name === 'class1_field') { 
     $this->checkType($name, $value, 'class1_required_type'); 
    } else { 
     $this->data[$name] = $value; 
    } 
    } 
    function dump() { 
    foreach ($this->data as $key => $value) { 
     print "$key: " . get_class($value) . "\n"; 
    } 
    } 
} 

class class2 extends class1 { 
    function mySet($name, $value) { 
    print "In class2::mySet()\n"; 
    if ($name === 'class2_field') { 
     $this->checkType($name, $value, 'class2_required_type'); 
    } else { 
     parent::mySet($name, $value); 
    } 
    } 
} 

class class3 extends class2 { 
    function mySet($name, $value) { 
    print "In class3::mySet()\n"; 
    if ($name === 'class3_field') { 
     $this->checkType($name, $value, 'class3_required_type'); 
    } else { 
     parent::mySet($name, $value); 
    } 
    } 
} 

class class4 extends class3 { 
    function mySet($name, $value) { 
    print "In class4::mySet()\n"; 
    if ($name === 'class4_field') { 
     $this->checkType($name, $value, 'class4_required_type'); 
    } else { 
     parent::mySet($name, $value); 
    } 
    } 
} 

$obj = new class4; 
$obj->mySet('class3_field', new class3_required_type); 
$obj->dump(); 

我试图避免“checkType()”函数的重复,但仍提供即使在层次结构得到任意大的正确的行为。

更为优雅的解决方案当然是最受欢迎的。

2

得到它的工作,你可以修改你的BASE_CLASS这样的:

class base_class { 
    function do_something() { 
    print "base_class::do_something()\n"; 
    } 

function inherit_this() { 
    $this->do_something(); 
} 
} 

然后你top_clas将调用基类的inherit_this(),但会有一个递归:do_something()的top_class调用$ this-> inherit_this(),并在base_class中再次调用$ this-> do_something()(在您的基类$中,这将引用您的top_class)。因此,您将一遍又一遍地调用inherit_this()。

您应该重命名方法来防止这种情况。

更新

如果您希望BASE_CLASS inherit_this()打印 “BASE_CLASS :: do_something” 你可以修改你这样的BASE_CLASS:

class base_class { 
    function do_something() { 
    print "base_class::do_something()\n"; 
    } 

    function inherit_this() { 
    base_class::do_something(); 
    } 

}

在这种情况下,你对base_class方法do_something()进行静态调用。输出是top_class::do_something() base_class::do_something()

更新2

关于你的评论,你可以修改你的BASE_CLASS这样的:

class base_class { 
    function do_something() { 
    print "base_class::do_something()\n"; 
    } 
    function inherit_this() {  
    $par = get_parent_class($this); 
    $par::do_something(); 
    } 
} 

你得到parrent类的$这一点,然后调用该方法。输出将是:top_class::do_something() middle_class::do_something()

+1

我想让它调用middle_class :: do_something(),因为真正的代码以不同的方式处理层次结构中的每个层次的数据,并且我想遍历层次结构一直到基层而不重新实现inherit_this ()在每个级别。 –

+0

@RickKoshi啊行!我会更新 – Grrbrr404

+0

这似乎有效,但我不能动摇它后面可能会引入一些难以发现的错误的感觉,因为它实际上调用middle_class :: do_something()作为静态方法,而不是方法$此。无论如何,这仍然是设置,只是因为PHP的奇怪范围。我还没有想到一个它会破的例子,但我很紧张。我想也许'call_user_func(array($ this,get_parent_class($ this)。“:: do_something”))'可能会更好,但是我也没有那么好的感觉。 –

0

我不太确定我明白你为什么想这样做。但我想你不能这样做。我知道你可以创建一个middle_class2并且能够继承它,然后它将成为middle_class2而不是middle_class的dosomething你打电话?!

所以我想你需要在middle_class创建

function inherit_this() { 
    parent::do_something(); 
    } 

我想过一个get_class($ this):: parent :: do_something()..但是没有奏效。

只是要确定..你想调用middle_class :: do_something()对吗?

+0

正确,完全访问$ this的属性和方法 –

0
class base_class { 
    function do_something() { 
    print "base_class::do_something()\n"; 
    } 
    function inherit_this() { 
    //parent::do_something(); 
    $class = get_called_class(); 
    $class::do_something(); 
    } 
} 
+1

解释为什么这个作品会很棒! – PearsonArtPhoto