2010-12-06 61 views
2

我試圖理解接口。C#接口問題

從我所瞭解的接口來說,它們與類一起使用,並允許類附加到接口類? 我不太瞭解這個概念。何時和爲什麼要使用此?我正在從一本書中讀到它將行爲放入類中,然後通過連接一個通用對象可以有多種行爲?

創建類似

Vehicle myObject = new Vehicle(); 
    Interface1 something = myObject; 
    something.someFunc(); 


Interface Interface1 { 
    void someFunc(); 
} 

回答

6

接口是行爲的合同。它說「如果你實施我,你必須做這些事情」。任何實現接口的類都必須符合該合同(即提供所有接口中指定的所有內容的具體實現)才能編譯。

從執行中分離出行爲是重用的一個例子。

在C#中,類可以實現許多接口,但只能從一個類繼承。由於C#不支持多重繼承(謝天謝地),接口是一種產生類似的東西的方法。

0

將接口想象成你的類應該包含的內容的定義,然後將其應用到類中,然後該類需要從接口定義這些函數。

MyClass : IMyInterface 

這對多態功能很有用,當你可能有類似的對象實現相同的功能,但其中的代碼是不同的。

2

你可以想象一個像契約一樣的接口。實現接口的類型必須提供接口中定義的所有方法。而且,其他代碼可以將您的類型的實例視爲接口的實例,而無需知道確切的類型。例如,對於插件體系結構,在運行時加載插件以及事先無法預先知道哪種類型實現您的接口,這會非常有用。通過接口,您可以定義一個IPlugin接口並查找實現它的類型。

1

接口是保證特定行爲存在的一種方式。

爲了詳細說明你上面的例子

something.someFunc(); 

你需要在你的代碼這一點什麼,是,無論是傳遞給你的對象,它應該有someFunc()方法來實現。

在這種情況下,您傳遞的是Vehicle

現在,假設這個代碼是一個方法和內部代替

void function ThisMethodCallsSomeFunc (Interface1 myObject) 
{ 
    myobject.someFunc(); 
} 

現在,在該方法中,我可以通過車輛的myObject的(只要車輛實現接口1)。然而,另外,假設我有另一個類「RavenousBugBlatter」,並且實現了Interface1,我可以改爲將該對象傳遞給此ThisMethodCallsSomeFunc並調用someFunc

這是否有助於說明接口在這種情況下如何提供幫助?

1
interface IFlyable 
{ 
    void Fly(); 
} 

class Bird : IFlyable 
{ 
    public void Fly() { } 
} 

class Plane : IFlyable 
{ 
    public void Fly() { } 
} 

List<IFlyable> things = GetBirdInstancesAndPlaneInstancesMixed(); 
foreach(IFlyable item in things) 
{ 
    item.Fly(); 
} 

鳥和飛機有沒有共同的基類除Object,但你可以看到使用我們可以grouply對付他們在我們的節目相同的接口,因爲它們具有相同的「特性」:飛。

+0

+1:沒有以相同的方式處理公共基類的不同類型似乎是m e – Patrick 2010-12-06 09:46:55

0

讓我們做一個非常簡單的例子,你需要一個接口:

比方說,你是編程庫,以在屏幕上繪製的對象。 爲了這個目的,你可能有一個數字,可以得出,例如對象:

class Cube { 
void draw(//Draw a cube); 
} 

現在讓我們說有什麼東西,告訴那些對象繪製自己。如果只有一些立方體,很容易:「所有立方體:在屏幕上繪製自己」

但是現在您會希望擁有不同類型的對象!這裏就是一個接口的用武之地:

interface DrawableObject { 
void draw(); 
} 

class Cube:DrawableObject { 
void draw(//Draw the Cube); 
} 

class Triangle:DrawableObject { 
void draw(//Draw the Cube); 
} 

class Circle:DrawableObject { 
void draw(//Draw the Cube); 
} 

現在你可以這樣做:「所有DrawableObjects:繪製自己在屏幕上」!因爲Circle,Cube和Triangle都實現了DrawableObject,所以它們都必須具有「draw」方法。

+0

無法解釋爲什麼在您的示例中,DrawableObject不能是超類。 IE:爲什麼你想要實現一個接口而不是擴展一個超類。 – cHao 2010-12-06 10:01:29

+0

是的,如果draw()包含一些在DrawableObject的不同實現上一致的任務,那麼你是正確的。我沒有想到這一點。 – metter 2010-12-06 12:11:18

0

就像@Mitch Weat那樣,Interface是一個強制執行方法簽名代碼的合同。

嘗試查看類似掩碼的接口,可以通過此掩碼查看類,而不用詢問類是否能夠做到這一點。如果類實現接口,類將能夠執行接口的所有方法描述!

0

接口定義了一組實現類必須具有的屬性和方法。接口的主要用途是實現類可以作爲他們實現的任何接口傳遞,這可以簡化和麪向未來的代碼。

假設您想創建一個方法,將集合中的所有數字相加。如果沒有接口,你不得不迎合每種類型的集合:ArrayList,List,Queue,Stack,int [],LinkedList,等等。 (還有很多很多)。但是,所有這些類都具有通過其接口定義的常見行爲,例如添加,刪除和迭代。在這種情況下,你真正需要的是遍歷集合的能力,所以你的方法是這樣的:

public static int Sum(IEnumerable listOfInts) 
{ 
    int total = 0; 

    foreach (object obj in listOfInts) 
    { 
     if (obj is int) 
      total += (int)obj; 
    } 

    return total; 
} 

現在你可以在任何對象傳遞,只要它實現IEnumerable,這是所有藏品做。

int total = Sum(new int[] { 3, 51, -2, 4 }); 

或者:

ArrayList list = new ArrayList(); 

list.Add(4); 
list.Add(52); 
... 
int total = Sum(list); 
0

一種方式是接口可以在現實世界中的商業意識是有益的是,如果你允許第三方開發者開發的應用程序的插件。

例如,讓我們拿一個銷售點的應用程序。此應用程序可與一系列外設配合使用 - 例如Symbol LS2208條形碼掃描儀,Avery-Berkel Scales等。每個設備都以不同的方式操作和與軟件進行通信,但您的POS軟件只知道一些設置命令 - 例如使用條形碼掃描器:ReadCode()IsCodeValid()Initialise()等。

下面的實現可能是任何東西,但你的POS軟件只關心這幾種方法。所以你可以定義一個名爲IBarcodeScanner的接口,它聲明瞭那幾個方法存根。

您的第三方開發人員想要添加對Symbol LS4015掃描儀的支持,例如,通信方式不同。他們爲它編寫自己的驅動程序,然後編寫界面中定義的幾個方法來公開所有功能。然後,您的POS軟件可以調用這4種方法,並保證它可以工作 - 它不必關心該開發人員完成的所有定製,它只是使用它所知道的方法。在更大規模的開發中讓生活更輕鬆。

1

我真的很喜歡Ninject文檔中解釋事物的方式,所以我只是使用它們的示例。你總是可以在這裏閱讀完整的文檔:https://github.com/ninject/ninject/wiki/_pages

比方說,你有一把劍類是這樣的:

class Sword 
{ 
    public void Hit(string target) 
    { 
    Console.WriteLine("Chopped {0} clean in half", target); 
    } 
} 

的劍也碰到了什麼東西。現在假設你有一個武士班。這個武士階級使用劍攻擊。

class Samurai 
{ 
    private Sword _sword; 

    public Samurai() 
    { 
    _sword = new Sword(); 
    } 

    public void Attack(string target) 
    { 
    _sword.Hit(target); 
    } 
} 

這一切工作不錯,罰款是這樣的:

class Program 
{ 
    public static void Main() 
    { 
    Samurai warrior = new Samurai(); 
    warrior.Attack("the evildoers"); 
    } 
} 

你現在有被緊密耦合劍類武士階層。什麼時候你想擁有武士軍隊?有的使用劍,有的使用弓箭,有的使用Shuriken。每次添加新武器時,您都必須修改您的武士課程。因爲那就是劍,弓箭和手裏劍。他們都是武士可以使用的所有武器,擊中的東西。

這是接口的作用。讓我們抽象出的使用的接口武器攻擊功能:

interface IWeapon 
{ 
    void Hit(string target); 
} 

class Sword : IWeapon 
{ 
    public void Hit(string target) 
    { 
    Console.WriteLine("Chopped {0} clean in half", target); 
    } 
} 

class BowAndArrow : IWeapon 
{ 
    public void Hit(string target) 
    { 
    Console.WriteLine("Shot {0} right in the chest!", target); 
    } 
} 

class Shuriken : IWeapon 
{ 
    public void Hit(string target) 
    { 
    Console.WriteLine("Pierced {0}'s armor", target); 
    } 
} 

我們現在已經是一個接口IWeapon和三個類實現該接口。界面就像合同一樣。它說:「如果你實現了我,你必須提供Hit方法,該方法應該接受一個字符串參數,並且不應該返回任何東西」。

對於我們的武士有什麼變化?它現在可以使用如下的接口IWeapon:

class Samurai 
{ 
    private IWeapon _weapon; 

    public Samurai(IWeapon weapon) 
    { 
    _weapon = weapon; 
    } 

    public void Attack(string target) 
    { 
    _weapon.Hit(target); 
    } 
} 

現在,武士職業使用IWeapon。因爲實現IWeapon接口的每個類同意提供Hit方法的合同,所以Samurai類不需要知道或關心它正在使用的武器。它只知道它有一個武器,它可以擊中is。

像這樣:

class Program 
{ 
    public static void Main() 
    { 
    Samurai warrior1 = new Samurai(new Sword()); 
    Samurai warrior2 = new Samurai(new Shuriken()); 
    Samurai warrior3 = new Samurai(new BowAndArrow()); 

    warrior1.Attack("the evildoers"); 
    warrior2.Attack("the big guy in front"); 
    warrior3.Attack("the scared guy running away"); 
    } 
} 

我希望這有一定的道理。

0

接口的主要特點是允許潛在不同的對象層次派生類同等對待多態

public interface IDoSomething 
{ 
    string DoIt(); 
} 

public class ClassOne : TextBox, IDoSomething 
{ 
    public string DoIt() 
    { 
     return "OK from a textbox"; 
    } 
} 

public class ClassTwo : Panel, IDoSomething 
{ 
    public string DoIt() 
    { 
     return "OK from a panel"; 
    } 
} 

,然後你可以多態地使用它們

List<IDoSomething> items = GetMyItems(); 
foreach (var item in items) 
{ 
    Console.WriteLine(item.DoIt()); 
}