Interface(接口)
(本文轉載地址:http://blog.sina.com.cn/s/blog_574c993d0100d59n.html)
介紹:
C#中的接口提供了一種實現運行時的多態。通過接口可以使用相同接口的引用來訪問實現相同接口的不同類的方法,其實是使用虛方法通過相同的引用調用相同基礎的不同的類。
在開始前先使用簡單的短類例子來解釋接口的概念,下面的簡短的例子顯示接口的樣子。
P1.cs 程序代碼:
1 class Demo { 2 public static void Main() { 3 System.Console.WriteLine("Hello Interfaces"); 4 } 5 } 6 7 interface abc { 8 }
輸出:Hello Interfaces
編譯運行上面的程序運行程序並顯示出期望的結果。這段程序包含一個Demo類程序入門Main()方法中打印“Hello Interfaces”。在上面的程序中還定義了接口abc。abc接口是空的,可以在接口中添加一些元素。
P2.cs 程序代碼:
1 class Demo { 2 public static void Main() { 3 System.Console.WriteLine("Hello Interfaces"); 4 } 5 } 6 7 interface abc { 8 int x; 9 }
輸出:P2.cs(11,3): error CS0525: Interfaces cannot contain fields
錯誤!在C#的接口中不能包含字段例如變量。上面的程序在接口abc中聲明了一個整型變量x。編譯將會出錯。
P3.cs 程序代碼:
1 class Demo { 2 public static void Main() { 3 System.Console.WriteLine("Hello Interfaces"); 4 } 5 } 6 7 interface abc { 8 void xyz() { 9 System.Console.WriteLine("In xyz"); 10 } 11 }
輸出:P3.cs(11,8): error CS0531: 'abc.xyz()': interface members cannot have a definition
這次在接口中定義了xyz()方法C#編譯器發現了錯誤。這說明在接口中成員不能有定義。也就意味着如果在接口abc中僅僅只有方法的聲明編譯器將認為正確?
P4.cs 程序代碼:
1 class Demo { 2 public static void Main() { 3 System.Console.WriteLine("Hello Interfaces"); 4 } 5 } 6 7 interface abc { 8 void xyz(); 9 }
輸出:Hello Interfaces
上面的程序編譯運行正常產生期望的輸出結果。最后編譯成功。在C#的接口中僅僅包含方法的定義。現在看看方法的作用。接口是類實現的規范。也就是說接口規定了方法的原型並有類來實現接口所定義的方法原型。
因此在類Demo和接口abc結合在一起。
P5.cs 程序代碼:
1 class Demo : abc { 2 public static void Main() { 3 System.Console.WriteLine("Hello Interfaces"); 4 } 5 } 6 7 interface abc { 8 void xyz(); 9 }
輸出:
P4.cs(1,7): error CS0535: 'Demo' does not implement interface member 'abc.xyz()' P4.cs(11,8): (Location of symbol related to previous error) |
在上面的代碼中Demo和接口abc通過“demo : abc”聯系在一起,通常對於這個結合有一點小的誤會。類Demo需要負責定義接口abc中定義的方法原型。因此在上面代碼中的Demo沒有實現abc接口中定義的xyz的方法,上面的代碼出錯。為了修正問題,類Demo必須實現接口abc中定義的方法原型xyz。看下面的程序代碼。
P6.cs 程序代碼:
1 class Demo : abc { 2 public static void Main() { 3 System.Console.WriteLine("Hello Interfaces"); 4 } 5 6 void xyz() { 7 System.Console.WriteLine("In xyz"); 8 } 9 } 10 11 interface abc { 12 void xyz(); 13 }
輸出:
a.cs(1,7): error CS0536: 'Demo' does not implement interface member 'abc.xyz()'.'Demo.xyz()' is either static, not public, or has the wrong return type. a.cs(16,8): (Location of symbol related to previous error) a.cs(7,8): (Location of symbol related to previous error) |
又出現錯誤!類Demo實現了方法xyz但沒有足夠的訪問權限。在接口abc定義的方法xyz的訪問權限是public。看下面的代碼。
1 class Demo : abc { 2 public static void Main() { 3 Demo demo = new Demo(); 4 System.Console.WriteLine("Hello Interfaces"); 5 demo.xyz(); 6 } 7 8 public void xyz() { 9 System.Console.WriteLine("In xyz"); 10 } 11 } 12 13 interface abc { 14 void xyz(); 15 }
Hello Interfaces In xyz |
好的!上面的代碼編譯運行成功產生預期的輸出結果。正如前面提及的接口可以調用實現相同的接口的不同的類。因此,需要不同的實現相同接口的類。在上面的代碼中類Demo實現了接口abc。下面讓另一個類Sample也實現接口abc。
P8.cs 程序代碼:
1 class Demo : abc { 2 public static void Main() { 3 System.Console.WriteLine("Hello Interfaces"); 4 Demo refDemo = new Demo(); 5 refDemo.xyz(); 6 Sample refSample = new Sample(); 7 refSample.xyz(); 8 } 9 10 public void xyz() { 11 System.Console.WriteLine("In Demo :: xyz"); 12 } 13 } 14 15 interface abc { 16 void xyz(); 17 } 18 19 class Sample : abc { 20 public void xyz() { 21 System.Console.WriteLine("In Sample :: xyz"); 22 } 23 }
輸出:
In Demo :: xyz In Sample :: xyz |
上面的程序編譯運行成功生產期望的輸出結果。refDemo是類Demo的實例。refSample是類Sample的實例。這兩個類都實現了接口abc因此他們都實現了方法xyz()。從程序入口Main()方法中通過refDemo和refSample實例分別調用了類Demo和類Sample的xyz()方法。
現在有兩個不同的類實現了相同的接口此時顯示了如何從不同的類中使用相同的接口引用。
P9.cs 程序代碼:
1 class Demo : abc { 2 public static void Main() { 3 System.Console.WriteLine("Hello Interfaces"); 4 abc refabc = null; 5 refabc = new Demo(); 6 refabc.xyz(); 7 refabc = new Sample(); 8 refabc.xyz(); 9 } 10 11 public void xyz() { 12 System.Console.WriteLine("In Demo :: xyz"); 13 } 14 } 15 16 interface abc { 17 void xyz(); 18 } 19 20 class Sample : abc { 21 public void xyz() { 22 System.Console.WriteLine("In Sample :: xyz"); 23 } 24 }
輸出:
In Demo :: xyz In Sample :: xyz |
上面的代碼編譯運行程序產生了預期的輸出結果。在Main()方法中定義了接口引用refabc是接口abc類型。實例化為Demo在refabc中存儲了類Demo類定義的xyz()可以通過refabc來調用。接下去,實例化為Sample在refabc中存儲了類Sample類定義的xyz()可以通過refabc來調用。因此,可以通過共同的接口引用refabc來訪問不同的類Demo和Sample中的xyz()的方法。在下面的代碼中使用循環調用類Demo和Sample實現相同接口abc使用單一接口引用refabc類型匹配的接口abc的類的實現。
P10.cs 程序代碼:
1 class Demo : abc { 2 public static void Main() { 3 abc[] refabc = { new Demo(), new Sample() }; 4 for(int i = 0; i <= 1; i++) 5 refabc[i].xyz(); 6 } 7 8 public void xyz() { 9 System.Console.WriteLine("In Demo :: xyz"); 10 } 11 } 12 13 interface abc { 14 void xyz(); 15 } 16 17 class Sample : abc { 18 public void xyz() { 19 System.Console.WriteLine("In Sample :: xyz"); 20 } 21 }
輸出:
In Demo :: xyz In Sample :: xyz |
上面的代碼編譯運行程序產生了預期的輸出結果。refabc是一個類型為abc接口的數組。它保存了類Demo和Sample的對象的引用。在for循環中,使用數字refabc,可以調用類Demo和Sample中的方法xyz()。一個類可以實現多個接口。看下面的程序。
P11.cs 程序代碼:
1 class Demo : abc, def { 2 public static void Main() { 3 System.Console.WriteLine("Hello Interfaces"); 4 abc refabc = new Demo(); 5 refabc.xyz(); 6 } 7 8 public void xyz() { 9 System.Console.WriteLine("In xyz"); 10 } 11 12 public void pqr() { 13 System.Console.WriteLine("In xyz"); 14 } 15 } 16 17 interface abc { 18 void xyz(); 19 } 20 21 interface def { 22 void pqr(); 23 }
輸出:
Hello Interfaces In xyz |
上面的代碼編譯運行程序產生了預期的輸出結果。類Demo實現了接口abc並且實現了xyz()方法。類Demo也實現了def接口也實現了pqr()方法。refabc是類型為abc接口的變量是類Demo的實例。可以通過refabc的實例調用Demo中xyz()方法就像refabc是接口abc的類型包含了xyz()方法的原型
P12.cs 程序代碼:
1 class Demo : abc, def { 2 public static void Main() { 3 System.Console.WriteLine("Hello Interfaces"); 4 abc refabc = new Demo(); 5 refabc.xyz(); 6 refabc.pqr(); 7 } 8 9 public void xyz() { 10 System.Console.WriteLine("In xyz"); 11 } 12 13 public void pqr() { 14 System.Console.WriteLine("In xyz"); 15 } 16 } 17 18 interface abc { 19 void xyz(); 20 } 21 22 interface def { 23 void pqr(); 24 }
輸出:
P11.cs(9,5): error CS0117: 'abc' does not contain a definition for 'pqr' |
錯誤!嘗試通過定義為接口abc類型的變量refabc的Demo實例來訪問pqr()方法,在接口abc中包含了函數xyz()的原型但沒有包含pqr()方法原型。可以通過類型為接口def的Demo實例來方法pqr()方法因為接口def包含方法pqr()的原型。