2011-10-31 248 views
6

紅寶石是否有其他OOP語言(例如:PHP)使接口無用?它有這種替代嗎?爲什麼Ruby人說他們不需要接口?

編輯:

一些澄清:

  • 在其他語言(例如:PHP),你不 「需要」 的接口(他們是不是在代碼級別強制)。您使用它們來簽訂合同,以改進軟件的體系結構。因此,在Ruby中你肯定不需要接口/用你需要的其他語言接口,因爲XXX'是錯誤的。

  • 不,mixins不是接口,它們是完全不同的東西(PHP 5.4實現了mixins)。你甚至使用過接口嗎?

  • 是的,PHP是OOP。語言不斷演變,歡迎來到現在。

+5

PHP是一種OOP語言? *輕笑* – NullUserException

+0

http://en.wikipedia.org/wiki/Mixin – robinjam

+0

PHP 5(我認爲這是該版本)向PHP引入了OOP設計概念,但它並沒有使它成爲「OOP」語言。你現在可以編寫OOP風格的PHP代碼。 –

回答

0

我相信這是因爲Ruby是動態類型的,而其他語言是靜態類型的。您需要在PHP中使用接口的唯一原因是在傳遞對象時使用類型提示。

+0

可能是一個更具體的想法 - ruby​​不只是動態類型,它是鴨子類型。 – robinjam

+0

雖然我們正在拆分頭髮,鴨子打字是一種特定類型的動態打字;) –

+1

我知道,這就是爲什麼我說它不是_just_動態打字;)。它相關的原因是因爲在ruby中它是一個對象當前的一組方法和屬性,而不是它的超類或接口,它決定了它的「類型」。 – robinjam

-1

要看你通過接口的意思。

如果通過接口指的是您的語言中存在的具體對象,您從中繼承或實現,那麼您不使用像Ruby這樣的語言中的接口。

如果你的意思是接口在對象中有一些記錄良好的接口,那麼當然是,對象仍然有一個良好的文檔接口,他們有你期望在那裏的屬性和方法。

我同意接口是存在於你的頭腦和文檔中的,而不是作爲對象存在於代碼中。

+0

是的,我知道你不使用Ruby中的接口,但我想知道爲什麼(除了該功能不可用) – HappyDeveloper

+0

@HappyDeveloper哦,我想這不是obvouis。爲什麼讓他們在代碼中。它膨脹。頭腦中有接口,在代碼中不需要構造。除此之外,對於那些沒有實現合適的輸入系統的語言來說,這是一種骯髒的破解。你不需要一個接口,你需要一個在你的嚴格類型語言中定義明確的類型。 – Raynos

+0

如果我創建了類,我可以讓他們在我的腦海裏(有限的時間),但是我旁邊的開發者呢?他們只需要猜測。接口有一個非常明確的作用,我不知道你的意思是「他們是黑客」。 Php也是動態的,但接口非常有用。例如,你將如何實現Bridge模式? – HappyDeveloper

3

由於ruby是duck-typed,不需要單獨的接口,但對象只需要實現常用的方法。看「經典」下面的例子:

class Duck 

    def move 
    "I can waddle." 
    end 

end 

class Bird 

    def move 
    "I can fly." 
    end 

end 

animals = [] 
animals << Duck.new 
animals << Bird.new 

animals.each do |animal| 
    puts animal.move 
end 

在這個例子中,「接口」是move方法,該方法是由DuckBird類既實現。

+0

在這裏,我只能看到他們之間沒有連接的兩個類。這與其他語言有什麼不同?在其他語言中,您可以做同樣的事情,也可以添加合同(通過界面),儘管它不是強制性的 – HappyDeveloper

+0

@Happy,不同之處在於在(大多數)靜態類型語言中,您必須使用顯式接口來「連接「這兩個班。 –

+0

@WayneConrad我知道我們沒有談論能夠在這個線程中沒有顯式接口的情況下做到這一點的優缺點,但它會很好。他們對我而言並不是很明顯。你能詳細說明嗎? – gabe

11

嗯,這是一個共識,當一個對象在Ruby中傳遞時,它不是經過類型檢查的。 Java和PHP中的接口是一種確認對象符合某種合約或「類型」的方式(因此可能是Serializable,Authorizable,Sequential以及其他任何您想要的)。

但是,在Ruby中沒有一個合同的正式概念,其中接口將履行一些有意義的作用,方法簽名中未檢查接口一致性。例如,參見Enumerable。當你將它混合到你的對象中時,你正在使用它的功能而不是聲明你的對象是Enumerable。讓您的對象爲Enumerable的唯一好處是定義了each(&blk),您將自動獲得map,select和朋友。您可以完美地擁有一個實現Enumerable提供的所有方法的對象,但不會混入模塊中,它仍然可以工作。

例如,在Ruby中一個期望的IO對象,你可以在一些有什麼做一個IO飼料,然後它會用一個錯誤或爆炸的任何方法 - 如果你正確地執行你的IO存根 - 即使傳遞的對象沒有被聲明爲「IO-ish」,它也能正常工作。

這背後的想法來自這樣一個事實,即Ruby中的對象並不是真正的榮耀的哈希表,其標籤貼在它們上面(然後有一些額外的標籤告訴解釋器或編譯器該對象具有接口X,因此它可以在上下文Y中使用),但是是一個封閉的實體來響應消息。所以如果一個對象響應一個特定的消息,它會滿足合同,如果它沒有迴應那個消息 - 那麼會出現錯誤。

因此,缺少接口的部分原因是模塊的存在(它可以包含您在未對調用者/消費者做任何類型承諾的情況下達到的功能),部分由消息傳遞的傳統而不是鍵入http://stardict.sourceforge.net/Dictionaries.php下載。

你應該看Jim Weirich的一些演講,因爲他廣泛涉及這個主題。

+0

謝謝,我到家後會看到它們 – HappyDeveloper

3

這個問題是一種開放式的,但這裏是我的看法:

接口聲明的目的是兩件事情:

  1. 聲明你的未來的自己或同事什麼方法這個類必須
  2. 聲明到您的電腦用什麼方法這個類必須有

如果我們先來第二個目的,Ruby源代碼是從來沒有組合物1因此,從來沒有一種方法可以驗證接口聲明的一致性,並警告開發人員不符合要求。這意味着如果Ruby有一些內置的接口支持,它將不會有一個選項來驗證一致性,直到運行時,應用程序無論如何都會崩潰,因爲缺少實現。

回到第一個目的。代碼可讀性。這可能是有道理的,指定接口的正式Ruby約定可能會有所幫助。現在,您可能會使用註釋或規範來進行交流,或者我可能會傾向於使用聲明式模塊包含。例如。

module Shippable 
# This is an interface module. If your class includes this module, make sure it responds to the following methods 

    # Returns an integer fixnum representing weight in grams 
    def weight 
    raise NotImplementedError.new 
    end 

    # Returns an instance of the Dimension class. 
    def dimensions 
    raise NotImplementedError.new 
    end 

    # Returns true if the entity requires special handling. 
    def dangerous? 
    raise NotImplementedError.new 
    end 

    # Returns true if the entity is intended for human consumption and thereby must abide by food shipping regulations. 
    def edible? 
    raise NotImplementedError.new 
    end 

end 

class Product 
    include Shippable 
end 

執行這個接口是通過創建,創建每一個包括Shippable模塊類的實例,調用四種方法,並希望他們沒有提出NotImplementedError一個規範的方式。

+0

只需要注意一點,您不需要使用'.new'顯式實例化'NotImplementedErrors' - 您可以'引發NotImplementedError'並且它可以工作。 – Russell

+0

據我所知,接口對測試有好處,因此在測試過程中,您不需要注入所有服務,提供者等的真實實現。我知道您可以在Ruby測試期間創建存根,但是你必須記得然後去模擬所有應該被嘲笑的東西。但是編程中的「不得不記住」的東西並不是編寫軟件的好方法,特別是當你在一個團隊中工作時。 – cryss

2

我是'Ruby人',我想要接口或類似的東西。

不強制執行合同 - 因爲強制執行任何事情都不是Ruby,並且有點違背了動態語言,反正沒有「強制執行」的「編譯」步驟 - 但是要記錄客戶端子類的合同可以選擇符合(或不符合,但如果他們選擇不這樣做,他們不能抱怨,如果代碼不起作用)。

當我碰到這樣的情況,即,當我在寫一個類或模塊我希望子類來提供,我通常會記錄我希望子類來提供這樣的方法方法:

module Enumerable 
    def each 
    raise NotImplementedError, "Subclasses must provide this method" 
    end 
end 

這並不理想,但這是一個相當罕見的情況,它適用於我。

相關問題