2011-11-25 153 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