2012-03-28 48 views
2

這是我的課:PHP類函數包裝

class toyota extends car { 
    function drive() { 
    } 
    function break() { 
    } 
} 

class car { 
    function pre() { 
    } 
} 

有什麼辦法,我可以這樣做,當我運行$小車 - >驅動器(),$小車 - >破()(或任何其他功能在豐田),它會調用$ car-> pre()之前調用豐田功能?

+0

閱讀在「構造函數」函數上......這可能是你需要的。 – 2012-03-28 04:38:09

+0

你能澄清一下嗎?無論何時您創建新對象或任何時候調用$ car方法,我都無法確定是否要運行$ car-> pre()。下面的答案涵蓋了兩個 - 我只是不知道哪一個模型。 – 2012-03-28 04:42:59

回答

10

是的。您可以使用protected和一些__call魔術:

class toyota extends car { 
    protected function drive() { 
     echo "drive\n"; 
    } 
    protected function dobreak() { 
     echo "break\n"; 
    } 
} 

class car { 
    public function __call($name, $args) 
    { 
     if (method_exists($this, $name)) { 
      $this->pre(); 
      return call_user_func_array(array($this, $name), $args); 
     } 


    } 

    function pre() { 
     echo "pre\n"; 
    } 
} 

$car = new toyota(); 
$car->drive(); 
$car->dobreak(); 

http://ideone.com/SGi1g

+0

這不僅是使用__call(正確方法)的唯一答案,而且它也是唯一一個實際執行一些method_exists檢查並實際調用最初調用的方法的方法。做這個! – sberry 2012-03-28 04:46:32

+0

你的意思是私人而不是保護?原因保護仍然可以通過父母和繼承可見。 – Patrick 2012-03-28 04:50:30

+0

@sberry,使用method_exists()進行檢查會隱藏調用無效方法時收到的默認錯誤 – Starx 2012-03-28 05:00:03

1

你可以做以下事情,但我不認爲這就是你想要的。

class toyota extends car { 
    function drive() { 
     $this->pre(); 
    } 
    function break() { 
     $this->pre(); 
    } 
} 

class car { 
    function pre() { 
    } 
} 

你可能想看看PHP特定的魔術方法。 http://php.net/manual/en/language.oop5.magic.php

-2

只需添加一個constructor,像這樣...

class toyota extends car { 
    function __construct() { 
     $this->pre(); 
    } 

    function drive() { 
     echo "drive!"; 
    } 

    function dobreak() { 
     echo "break!"; 
    } 
} 

class car { 
    function pre() { 
     echo "Hello!"; 
    } 
} 

$car = new toyota(); 
$car->drive(); 
$car->dobreak(); 

Classes which have a constructor method call this method on each newly-created object, so it is suitable for any initialization that the object may need before it is used.

break被保留,所以你不應該將其用作函數名稱。

+0

我認爲他正在尋找一種方法來在函數調用之前運行'pre'方法,而不是在對象初始化時 – blackpla9ue 2012-03-28 04:43:11

+0

回覆時我被中斷了。我用構造函數更新了我的示例。它仍然在做這項工作。 – Bjoern 2012-03-28 06:24:17

0

這將更好地與魔術方法進行所謂的__call()

public function __call($name, $arguments) 
{ 
    $this -> pre(); 
    return $this -> $name($arguments); 
} 

這是什麼方法?它覆蓋默認的方法調用,因此可以調用preCall狀態。

toyota

class toyota extends car {  

    public function __call($name, $arguments) 
    { 
     $this -> pre(); 
     return call_user_func_array(array($this, $name), $arguments); 
    } 

    function drive() { 
    } 
    function break() { 
    } 
} 
+0

'$ this - > $ name($ arguments)'---將調用所有以數組形式傳遞的參數。因此'$ car-> drive(1,2)'將會被'$ car-> drive(array(1,2))'重新調用,這只是不正確的 – zerkms 2012-03-28 07:46:30

+0

@zerkms,你說得對。更新 – Starx 2012-03-28 08:00:39

0

如果你正在使用PHP5(> = 5.3.2),存在與聲明的所有方法爲私有有效的解決方案。這將強制方法調用從一個函數調用:

exec_method() 

運行在:http://ideone.com/cvfCXm

的代碼片段是在這裏:

<?php 

    class car { 

     //method to get class method 
     public function get_method($method_name) { 
      $class = new ReflectionClass(get_class($this)); 
      $method = $class->getMethod($method_name); 
      $method->setAccessible(true); 
      return $method; 
     } 

     public function exec_method($method_name, $arg_args=array()) { 

      //execute the pre() function before the specified method 
      $this->pre(); 

      //execute the specified method 
      $this->get_method($method_name)->invokeArgs($this, $arg_args); 
     } 

     public function pre() { 
      echo 'pre'; 
      echo '<br />'; 
     } 
    } 

    class toyota extends car { 
     private function drive() { 
      echo 'drive'; 
      echo '<br />'; 
     } 

     private function brake() { 
      echo 'brake'; 
      echo '<br />'; 
     } 
    } 

    $toyota = new toyota(); 
    $toyota->exec_method('drive'); 
    $toyota->exec_method('brake'); 
?> 

參考:

Answer to Best practices to test protected methods with PHPUnit [closed]