2010-09-13 56 views
3

我已經研究了PHP的操作系統和可重用代碼的概念。PHP:如何重用代碼(oop)?

我已經見過像

interface iTemplate 
{ 
    public function setVariable($name, $var); 
    public function getHtml($template); 
} 
And implement it: 

// Implement the interface 
class Template implements iTemplate 
{ 
    private $vars = array(); 

    public function setVariable($name, $var) 
    { 
     $this->vars[$name] = $var; 
    } 

    public function getHtml($template) 
    { 
     foreach($this->vars as $name => $value) { 
      $template = str_replace('{' . $name . '}', $value, $template); 
     } 

     return $template; 
    } 
} 

一個例子,我可以理解的代碼,但不知道爲什麼它是可重複使用。每次我想在iTemplate界面添加一個新功能時,我的Template類也需要改變。我不明白「重用」的概念。我感謝任何幫助。謝謝。

+0

你能告訴我你在哪裏找到那個代碼嗎?我正處於學習階段,我希望通過實例學習。 – dole 2011-02-25 18:27:04

回答

6

接口是不能直接用於代碼重用。他們是爲了抽象。它們啓用使用該模板的類來檢查接口而不是基本模板類。這樣它就將接口聲明中的實現分開了。

因此,如果您的方法對template類執行了某些操作,那麼檢查實例template的對象將難以編碼對該類的依賴性。但事實上,你並不在乎你得到的是什麼課程,你只是在乎它是否遵守了界面(因爲這就是你所打的所有東西)。

public function foo(Template $template) { 

VS:

public function foo(iTemplate $template) { 

現在,只要代碼複用,接口是不是真的設計了點。繼承通常是。基本上認爲繼承是擴展抽象。讓我舉個例子:

如果你要爲鳥類創建一組類,你可以通過繼承來處理它,如果沒有它的話。讓我們來看看我們如何做到這一點沒有:

interface iBird { 
    public function fly(); 
    public function speak(); 
    public function swim(); 
    public function walk(); 
} 

class Duck implements iBird { 
    public function fly() { 
     //Fly here 
    } 
    public function speak() { 
     // Quack here 
    } 
    public function swim() { 
     //Swim here 
    } 
    public function walk() { 
     //Walk here 
    } 
} 

class Turkey implements iBird { 
    public function fly() { 
     //Fly here, but limited 
    } 
    public function speak() { 
     //Make turkey sound here 
    } 
    public function swim() { 
     throw new Exception('Turkeys can not swim!'); 
    } 
    public function walk() { 
     //Walk here 
    } 
} 

現在,這是一個簡單的例子,但是你可以看到,在這兩個鳥,walk()功能將可能是相同的(並因此違反DRY)...

讓我們來看看如何看起來與單層繼承:

abstract class Bird implements iBird { 
    public function fly() { 
     //Fly here 
    } 
    abstract public function speak(); 
    public function swim() { 
     //Swim here 
    } 
    public function walk() { 
     //Walk here 
    } 
} 

class Duck extends Bird { 
    public function speak() { 
     //Quack here 
    } 
} 

class Turkey extends Bird { 
    public function speak() { 
     //Make turkey sound here 
    } 
    public function swim() { 
     throw new Exception('Turkeys can not swim!'); 
    } 
} 

現在,你可以看到,我們只是重新使用的方法3!我們沒有聲明speak(),因爲它會一直被覆蓋(因爲沒有兩隻鳥聽起來一樣)。

聽起來不錯吧?那麼,根據我們的需要,我們可能需要添加其他抽象類型。因此,我們可以說我們製作了許多不同類型的鳥類......我們會有一些不會游泳的,因此我們可能會創建一個抽象類NonSwimmingBird,它擴展Bird,但是會爲我們引發異常。或者NonFlyingBirdShortRangeBird ...

現在,儘管代碼重用,但我們在其他區域遇到了問題。假設我們有一隻不會飛翔或游泳的鳥。我們繼承什麼課程?無論哪種方式,我們都在複製代碼。所以我們需要找到另一條出路。那麼,我們該怎麼做呢?通過Design Patterns ...我們可以使用裝飾器模式來實時添加這些特徵,而不是直接繼承。 (還有其他的模式可以用在這裏,重點是要證明單獨的繼承並不適合所有的需求,單獨的模式也不會,你需要一個好的架構來根據你的確切需求來使用兩個世界) ...

問題是,這一切都取決於您的需求。如果你只有2個「班級」的對象,那麼你將構建一個比如果你計劃擁有數千個更簡單的東西。我寫在這裏的目的是爲了演示如何使用直接繼承來實施一些DRY主體(但也包括直接繼承如何導致代碼重複)。最重要的是,不要因爲你不想重複自己而堅持DRY。堅持DRY,但要確保你在合理的地方進行組合和擴展,否則你會造成自己的維護頭痛。堅持Single Responsibility Principal,你應該沒問題...

+0

非常非常好的解釋....感謝一百萬。 – FatDeveloper 2010-09-13 19:31:27

0

接口只寫1處於發展的開始時間。只有在寫這個接口的其他類實現之後。界面 - 是一個基礎。 注意:方法setVariable不是必需的。 PHP中有很多神奇的方法,如__get()__set()

+0

謝謝。但是假設我們創建了另一個名爲Product implement iTemplate的類。我仍然需要在類中輸入setVariable和getHtml方法,不管是否實現接口,所以有什麼意義? – FatDeveloper 2010-09-13 16:21:25

0

接口通常在你想要的東西是可以互換的情況下非常有用。想象一下你會構建一個支持插件的應用程序。然後你有接口iPlugin:

interface iPlugin { 
    public function init(); 
    /* .. */ 
} 

和所有的插件將實現該接口。然後,插件管理器可以輕鬆檢查插件是否實現了接口並調用其上的init()方法。

0

代碼並不需要是OO受到重用,但在很多情況下沒有什麼幫助。

代碼當然不需要在某些情況下,這將有助於使用接口是可重複使用的,雖然一次。

編寫可重用代碼的關鍵是編寫明確編寫的代碼,經過充分評論,使用一致的命名和調用約定,而且比通常需要解決的問題更爲通用。

在PHP中編寫可重用代碼的最簡單和最強大的技術之一是編寫接受可變數量參數或接受參數關聯數組的方法。

通常情況下,沒有開始「打算」重新使用的代碼就是您想要重用的東西。通常情況下,代碼開始「內聯」,然後你發現你需要在不止一個地方完全或幾乎完全相同的事情。當你發現自己複製和粘貼代碼時,是時候將它重構爲一個函數。

同樣,當你發現自己希望在文件X中定義的函數在文件Y中真正有用時,是時候將它移動到模塊中。

學習這一切的最好方法是通過經驗。有些人會告訴你從一開始就設計這些東西,如果你有這樣的洞察力和經驗,這當然是一個好主意,但從底部開始這樣做也是有效的,這可能是最好的方法學習。

0

面向對象編程的可重用性是使用以前的類或函數或方法在本類中,但沒有以前的類的問題。