2011-06-22 70 views
4

給定一個基類,其中有一些必須在特定方法之前和之後運行的邏輯,它在其不同的派生類中採用截然不同的參數。 作爲一個例子:在PHP中執行掛鉤方法

abstract class Base{  
    public function pre(){ print "Runing Base::pre()\n"; } 
    public function pos(){ print "Runing Base::post()\n"; } 
    abstract public function doIt(); 
} 

class Cheating extends Base 
{ 
    public function doIt(){ 
     $this->pre(); 
     print "Doing it the cheating way\n"; 
     $this->pos(); 
    } 
} 

但是其實我喜歡做的是沿着線:

class Alpha extends Base 
{ 
    public function doIt($x, $y){ 
     print "Doing it in Alpha with x=$x, y=$y"; 
    } 
} 

class Beta extends Base 
{ 
    public function doIt($z){ 
     print "Doing it in Alpha with z=$z"; 
    } 
} 

,並有一些方法來始終運行前和POS機的方法,而不必改變doIt方法本身。

最顯而易見的方法,應該doIt方法是同質的跨庫的所有派生會是這樣的:

abstract class Base 
{ 
    public function pre(){ print "Runing Base::pre()\n"; } 
    public function pos(){ print "Runing Base::post()\n"; } 

    public function process($a,$b){ 
     $this->pre(); 
     $this->doIt($a,$b); 
     $this->pos(); 
    } 

    abstract public function doIt(); 
} 

class Wishful extends Base 
{ 
    public function doIt($a, $b){ 
     print "Doing it the Wishful way with a=$a, b=$b\n"; 
    } 
} 

問題存在是因爲我們有不同的參數個數和類型上的doIt方法的每個實現,它實際上並沒有解決問題。

這聽起來像是一個「鉤子」的情況 - 人們如何去實現這些?或者任何其他體面的解決問題的方式......我相信應該有一種更簡單的方式,我只是想念 - 可能是在圈子裏思考一件錯誤的事情。

謝謝!

+0

讓你的方法私人和使用魔術方法__call – datasage

回答

0

可變參數調用是可以做到的。將$ this作爲對象傳遞。

抓取的論點是有點棘手,但可以用__call來完成:http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.methods

+0

非常多,它對我來說看起來有點亂,但是哦... PHP不存在以滿足我微妙的美學:)謝謝,這將解決它。 – Wagemage

+0

:)我會盡可能地說它真的很醜:>將它與用python編寫的包裝方法進行比較.. –

0

這聽起來像你想要的東西,如:http://php.net/manual/en/function.call-user-func-array.php

function process() 
{ 
    $this->pre(); 
    $result = call_user_func_array(array($this, 'doIt'), func_get_args()); 
    $this->post(); 
    return $result; 
} 
+0

聽起來這種方式執行。有點gr but,但是......嘿,如果是的話,它就是這樣 - 謝謝! – Wagemage

2

你應該看看aspect-oriented programminglithium framework's filter系統使用這樣的東西。 Zend Framework 2也計劃使用AOP。

如果要在引擎級攔截函數調用,可以使用PECL中的intercept

谷歌還顯示nice framework你可以從中學到很多東西。看看它的代碼。

而且,這裏是一個相關的SO問題:https://stackoverflow.com/questions/4738282/are-there-any-working-aspect-oriented-php-libraries

+0

很酷。我會看一看。 Ars longa,vita brevis ......和截止日期 - 但很有可能是值得的。謝謝 :) – Wagemage