2012-02-26 76 views
6

可能重複:
Interfaces: Why can't I seem to grasp them?
Why would I want to use Interfaces?爲什麼我需要界面?

我認爲這個問題是重複1000次,我再次問抱歉。我真的在尋找一個簡單的答案,爲什麼我明確需要接口,或者如果你請解釋一些我無法實現的接口。

如果它是多重繼承,那麼我會請求你給我一個簡單的例子,通過它我可以理解爲什麼我需要接口。

--Thx提前。

注:我問在.NET(C#)語言的背景下,這個問題

EDIT1:現在每當我試圖學習的界面我的頭腦告訴我 - >「哥們你要在一張白紙上畫出一個人的身體「但是你需要另一張白紙,在那裏你必須再畫出輪廓,畫出所有身體部位的顏色給他們以獲得真實的照片。」所以我爲什麼要浪費第一張白紙大綱

+0

這可能有助於:interfaces描述* p​​eripheral *屬性,抽象類定義* core *函數。 – Jason 2012-02-26 09:19:06

+0

如果你想讓你的項目支持不同的數據庫。以便客戶端可以在將來改變他的數據庫我們使用接口包含屬性程序在類文件中不會改變對象........ – 2012-02-26 09:19:24

+0

有幾十個這個問題的潛在重複...這裏有幾個:[1 ](http://stackoverflow.com/questions/240152/why-would-i-want-to-use-interfaces),[2](http://stackoverflow.com/questions/3355408/explaining-interfaces-to -students),[3](http://stackoverflow.com/questions/122883/interfaces-why-cant-i-seem-to-grasp-them) – 2012-02-26 11:23:51

回答

12

理解接口最簡單的方法是它們允許不同的對象暴露COMMON功能。這使得程序員可以編寫更簡單,更短的代碼來編寫接口,然後只要對象實現該接口就可以工作。

數據庫提供:

有許多不同的數據庫供應商中,MySQL,MSSQL,Oracle等。然而所有數據庫對象可以做同樣的事情,所以你會發現數據庫對象的多個接口。如果一個對象實現了IDBConnection,那麼它將暴露方法Open()和Close()。所以如果我希望我的程序是數據庫提供者不可知的,我就編程到接口而不是特定的提供者。

IDbConnection connection = GetDatabaseConnectionFromConfig() 
connection.Open() 
// do stuff 
connection.Close() 

見編程接口(的IDbConnection),我現在就可以在我的配置換出任何數據提供者,但我的代碼保持完全相同的。這種靈活性非常有用且易於維護。這樣做的缺點是我只能執行'通用'數據庫操作,可能無法充分利用每個特定提供商提供的優勢,因此編程中的所有內容都有所折衷,您必須確定哪種方案最有利於您。

類別:

如果您發現幾乎所有的收藏品實現此接口稱爲IEnumerable的。 IEnumerable返回具有MoveNext(),Current和Reset()的IEnumerator。這使C#可以輕鬆移動您的集合。它可以做到這一點的原因是因爲它暴露IEnumerable接口,它知道對象公開它需要通過它的方法。這有兩件事。 1)foreach循環現在將知道如何枚舉集合,並且2)現在您可以將強大的LINQ表達式應用於您的集合。同樣,接口在這裏非常有用的原因是因爲所有集合在COMMON中都有一些東西,所以它們可以通過。每個集合都可以通過不同的方式移動(鏈接列表vs數組),但接口的美妙之處在於,實現對於接口的消費者而言是隱藏的並且不相關的。 MoveNext()爲您提供了集合中的下一個項目,不管它如何實現。相當不錯,是吧?

多態性

當你設計自己的接口,你只需要問自己一個問題。這些東西有什麼共同點?一旦你找到了對象共享的所有東西,你就可以將這些屬性/方法抽象成一個接口,以便每個對象都可以繼承它。然後您可以使用一個界面針對多個對象進行編程。

當然,我必須給我最喜歡的C++多態的例子,動物的例子。所有動物都有一定的特徵。讓我們說他們可以移動,說話,他們都有一個名字。因爲我剛剛確定了我的所有動物的共同點,並且我可以將這些特徵抽象爲IAnimal接口。然後我創建一個Bear對象,一個Owl對象和一個Snake對象,它們都實現了這個接口。您可以將不同對象存儲在一起以實現相同接口的原因是因爲接口代表了IS-A替代權。一隻熊IS-A動物,一隻貓頭鷹IS-A動物,所以它使我可以將它們全部收集爲動物。

var animals = new IAnimal[] = {new Bear(), new Owl(), new Snake()} // here I can collect different objects in a single collection because they inherit from the same interface 

foreach (IAnimal animal in animals) 
{ 
    Console.WriteLine(animal.Name) 
    animal.Speak() // a bear growls, a owl hoots, and a snake hisses 
    animal.Move() // bear runs, owl flys, snake slithers 
} 

你可以看到,即使這些動物以不同的方式執行每一個動作,我可以在一個統一的編程模型,對他們的一切,這只是接口的衆多優勢之一。

所以接口最重要的事情就是對象有什麼共同點,以便您可以用同樣的方式對不同的對象進行編程。節省時間,創建更靈活的應用程序,隱藏複雜性/實現,模擬真實世界的對象/情況以及許多其他好處。

希望這會有所幫助。

+2

優秀的答案。 – 2012-06-14 23:42:58

+0

使用接口背後原理的最佳解釋之一。 – rajibdotnet 2014-05-10 18:34:29

+0

收藏答案。 +1。 – Jogi 2016-05-13 08:00:46

6

一個接口是一個合同該類可以做什麼,這意味着一個類可以實現多個合同秒。

抽象類是類應該如何表現的模板,每個類只能填充一個模板。

擴展類獲取現有對象並添加/更改功能,每個類只能擴展一個父類。

如果您想描述如何在沒有定義具體實現的情況下采取行動,您將使用合同(接口)。這個契約可以由任何其他實現所定義的方法/屬性的類來實現。

如果您想先指定功能的一部分,然後添加到其上,則可以使用抽象類。

編輯:考慮一下:

你有一個需要存儲一些數據說EntityA的應用程序,但你可以有多種方式,可以在其中存儲的數據(如XML,SQL數據庫,CSV ECT)。您可以爲這些不同的方法中的每一種創建一個類來存儲EntityA。但是當你想改變方法時,你需要明確指定你想要的類型。

public class DoStuffWithEntityA{ 
    public void DoStuffAndStoreAsXml(EntityA entity){ /*Logic*/} 
    public void DoStuffAndStoreAsCsv(EntityA entity){ /*Logic*/} 
    public void DoStuffAndStoreInDatabase(EntityA entity){ /*Logic*/} 
} 

prehaps這裏更好的辦法是使用說明,一般什麼東西,存儲EntityA會是什麼樣的接口。

public interface IStoreEntityA{ 
    void Store(EnitityA entity); 
} 

那麼你可以只說你想要的東西,存儲EntityA在你的代碼

public class DoStuffWithEntityA{ 
    private IStoreEntityA _entityAStorer; 
    public DoStuffWithEntityA(IStoreEntityA howIStoreEntityA){ _entityAStorer = howIStoreEntityA;} 
    public void DoStuff(EntityA entity) 
    { 
     //Do Stuff 
     _entityAStorer.Store(entity); 
    } 
} 

這意味着你的邏輯心不是緊耦合的方式你存儲EntityA

+0

感謝您的回答。但是,如果你閱讀我的新編輯,你會明白我心中發生了什麼。如果你給我一些例子,這將有所幫助。 Thx – 2012-02-26 09:50:58

+0

看到我在這裏編輯一個場景,基本上有時你可能不想/不需要知道如何實現某些東西,所以你只要求任何滿足特定合同的東西。 – 2012-02-26 10:08:22