簡體   English   中英

在Ruby中,C#中的接口相當於什么?

[英]In Ruby, what is the equivalent to an interface in C#?

我目前正在嘗試學習Ruby,而我正在嘗試更多地了解它在封裝和合同方面提供的內容。

在C#中,可以使用接口定義合同。 實現接口的類必須通過為每個定義的方法和屬性(以及可能的其他內容)提供實現來滿足合同中的條款。 實現接口的單個​​類可以在合同定義的方法范圍內執行任何需要,只要它接受相同類型的參數並返回相同類型的結果。

有沒有辦法在Ruby中強制執行此類操作?

謝謝

我在C#中的一個簡單例子:

 interface IConsole { int MaxControllers {get;} void PlayGame(IGame game); } class Xbox360 : IConsole { public int MaxControllers { get { return 4; } } public void PlayGame(IGame game) { InsertDisc(game); NavigateToMenuItem(); Click(); } } class NES : IConsole { public int MaxControllers { get { return 2; } } public void PlayGame(IGame game) { InsertCartridge(game); TurnOn(); } } 

ruby中沒有接口,因為ruby是一種動態類型語言。 接口基本上用於使不同的類可互換而不會破壞類型安全性。 您的代碼可以與每個控制台一起使用,只要它像C#中的控制台一樣實現IConsole。 “duck typing”是一個關鍵字,你可以用它來趕上處理這類問題的動態語言方式。

此外,您可以並且應該編寫單元測試來驗證代碼的行為。 每個對象都有一個respond_to? 您可以在斷言中使用的方法。

Ruby擁有接口 ,就像任何其他語言一樣。

請注意,您必須注意不要混淆Interface的概念,它是一個單元的職責,保證和協議的抽象規范,具有interface的概念,它是Java,C#和VB.NET中的關鍵字。編程語言。 在Ruby中,我們一直使用前者,但后者根本不存在。

區分這兩者非常重要。 重要的是接口 ,而不是interface interface幾乎沒有任何用處。 沒有什么能比Java中的標記接口更好地證明這一點,它們是完全沒有成員的接口:只需看看java.io.Serializablejava.lang.Cloneable ; 這兩個interface意味着非常不同的東西,但它們具有完全相同的簽名。

那么,如果兩個interface意味着不同的東西,具有相同的簽名,那么interface 究竟是什么保證你呢?

另一個好例子:

interface ICollection<T>: IEnumerable<T>, IEnumerable
{
    void Add(T item);
}

System.Collections.Generic.ICollection<T>.Add接口是什么?

  • 集合的長度不會減少
  • 之前收集的所有物品仍然存在
  • item在集合中

哪些實際出現在interface 沒有! interface中沒有任何內容表明Add方法甚至必須添加 ,它也可以從集合中刪除元素。

這是該interface的完美有效的實現:

class MyCollection<T>: ICollection<T>
{
    void Add(T item)
    {
        Remove(item);
    }
}

另一個例子:在java.util.Set<E>中,它實際上是說它是一個集合嗎? 無處! 或者更確切地說,在文檔中。 用英語。

在Java和.NET的幾乎所有interfaces ,所有相關信息實際上都在文檔中,而不是在類型中。 那么,如果類型不告訴你任何有趣的東西,為什么要保留它們呢? 為什么不堅持文檔? 而這正是Ruby所做的。

請注意,還有其他語言可以實際以有意義的方式描述接口 但是,這些語言通常不會調用描述接口interface ”的構造,它們稱之為type 在依賴類型的編程語言中,您可以例如表達sort函數返回與原始集合長度相同的集合的屬性,原始中的每個元素也在已排序的集合中,並且不會出現更大的元素在較小的元素之前。

簡而言之:Ruby沒有Java interface的等價物。 但它確實具有Java 接口的等價物,並且與Java:文檔中的完全相同。

此外,就像在Java中一樣, Acceptance Tests也可用於指定接口

特別是,在Ruby中,對象的接口由它可以什么決定,而不是它是什么class ,或者它混合了什么module 。任何具有<<方法的對象都可以附加到。 這在單元測試中非常有用,你可以簡單地傳入一個Array或一個String而不是一個更復雜的Logger ,即使ArrayLogger沒有共享一個顯式interface除了它們都有一個名為<<的方法。

另一個例子是StringIO ,它實現了與IO相同的接口 ,因此實現了File的大部分接口 ,但除了Object之外沒有共享任何共同的祖先。

接口通常被引入靜態類型的OO語言,以彌補多重繼承的缺失。 換句話說,他們更的必要之惡不是一些有用的本質每

另一方面,Ruby:

  1. 動態類型語言是“duck typing”,所以如果你想在兩個對象上調用方法foo ,它們既不需要繼承相同的祖先類,也不需要實現相同的接口。
  2. 通過mixins的概念支持多重繼承,這里也不需要接口。

Ruby並沒有真正擁有它們; 接口和契約通常更多地存在於靜態世界中,而不是動態。

如果你真的需要,有一個名為Handshake的寶石可以實現非正式合同。

Ruby使用模塊的概念作為接口的替代(有點)。 Ruby中的設計模式有很多關於這兩個概念之間差異的很好的例子,以及為什么ruby選擇更靈活的接口替代方案。

http://www.amazon.com/Design-Patterns-Ruby-Russ-Olsen/dp/0321490452

Jorg有一個很好的觀點,ruby有接口,而不是關鍵字。 在閱讀一些回復時,我認為這在動態語言中是否定的。 您必須創建單元測試,而不是使用編譯器捕獲方法,而不是通過語言強制執行接口。 它還使理解方法更難以推理,因為當你試圖調用它時你必須追捕一個對象是什么。

舉個例子:

def my_func(options)
  ...
end

如果你看一下這個函數,你就不知道它是什么選項以及它應該調用哪些方法或屬性,而不需要尋找單元測試,調用它的其他地方,甚至看看方法。 更糟糕的是,該方法甚至可能不使用這些選項,而是將其傳遞給其他方法。 為什么在編譯器捕獲時應該編寫單元測試。 問題是你必須以不同的方式編寫代碼來表達動態語言的這種缺點。

雖然有一個好處,那就是動態編程語言可以快速編寫一段代碼。 我不必編寫任何接口聲明,后來我可以使用新的方法和參數而無需訪問接口來公開它。 權衡是維護的速度。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM