程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#基本語法學習(九),

C#基本語法學習(九),

編輯:C#入門知識

C#基本語法學習(九),


C#中的接口

  在C#中接口是一組公共方法或屬性的集合。接口可以被其他接口或是類繼承,但不能被實例化。

    1、接口中包含的屬性和方法都是公共的,不是繼承或是私有的。事實上,在C#中定義接口中的成員時,不允許顯示指定接口成員的可訪問性,而是自動默認為公共的。

    2、接口中只能包含普通方法或屬性,而不能包含其他內容,如構造函數、變量等。

    3、當接口被某個類繼承時,通常說類實現了這個接口,而較少說類繼承了接口。

    4、接口中的方法和屬性只有簽名部分,而沒有實現部分,甚至連接口名後面的大括號也不能有,否則會出現編譯錯誤。

  在C#中用interface關鍵字定義一個接口

  訪問修飾符 interface 接口名

  {

    //接口成員(方法和屬性)

  }

  C#中約定接口的名字以字母I開頭。如以下代碼定義一個接口IPerson

 1     public interface IPerson
 2     {
 3         void eat(object food);      //接口的方法
 4         void speak(string text);    //接口的方法
 5 
 6         string name                 //接口的屬性
 7         {
 8             get;
 9             set;
10         }
11     }

  如前所述,接口中不允許定義變量、構造函數,不能顯示指定接口中方法或屬性的可訪問性。

 

  接口可以被類或者別的接口繼承。類繼承接口的語法與類繼承類的語法相同,都是在類名後面加冒號和要繼承的接口名,如下:

  訪問修飾符 class 類名:接口名

  {

    //類與接口的成員

  }

  類繼承接口與類繼承類的不同之處在於一個類可以同時繼承多個接口,但只能從一個類繼承。當一個類繼承多個接口時,多個接口之間用逗號隔開,如下:

  訪問修飾符 class 類名:[基類名][,接口1][,接口2][...][,接口n]

  {

    //類與接口成員

  }

  接口繼承接口與類繼承接口語法類似,只是定義接口時使用關鍵字interface。

  訪問修飾符 interface 接口名:[接口1][,接口2][,接口3][...][,接口n]

  {

    //接口成員

  }

  如果一個類從接口繼承,那麼這個類必須要實現接口中定義的所有方法和屬性。由於接口定義了方法和屬性的簽名,而這些方法和屬性的具體實現代碼是在從接口繼承的類裡寫,所以當一個類從接口繼承時,通常說一個類實現了某個接口。

  這裡所說的實現有兩層含義:首先說明類繼承於接口,其次,類中用代碼實現了接口中定義的方法和屬性。

  如果一個類實現了一個接口,由於類繼承自接口,所以類可以隱式轉換為接口,這與派生類向基類隱式轉換是一樣的。如果一個類實現了多個接口,那麼類可以隱式轉換為其中任意一個接口。

 1     public interface IPerson
 2     {
 3         void eat(object food);      //接口的方法
 4         void speak(string text);    //接口的方法
 5 
 6         string name                 //接口的屬性
 7         {
 8             get;
 9             set;
10         }
11     }
12 
13     public class Student:IPerson
14     {
15 
16         public void eat(object food)
17         {
18             Console.WriteLine(name + " eat: " + food.ToString());
19         }
20 
21         public void speak(string text)
22         {
23             Console.WriteLine(name + " say: " + text);
24         }
25 
26         private string _name;
27         public string name
28         {
29             get
30             {
31                 return _name;
32             }
33             set
34             {
35                 _name = value;
36             }
37         }
38     }
39         static void Main(string[] args)
40         {
41             IPerson person;
42             Console.WriteLine("Main: 通過接口調用方法");
43             person = new Student();
44             person.name = "Nick";
45             person.eat("apple");
46             person.speak("Hello");
47             Console.WriteLine("Main: 通過類調用方法");
48             Student s = new Student();
49             s.name = "Jessice";
50             s.eat("rice");
51             s.speak("Hehe");
52 
53             Console.ReadLine();
54         }

  結果

Main: 通過接口調用方法
Nick eat: apple
Nick say: Hello
Main: 通過類調用方法
Jessice eat: rice
Jessice say: Hehe

 

  顯式接口的實現

  使用顯式接口時,類中用來實現接口的方法名前面必須以接口名作為前綴。  

 1     public class NewStudent:IPerson
 2     {
 3 
 4         void IPerson.eat(object food)
 5         {
 6             Console.WriteLine(_name + " eat: " + food.ToString());
 7         }
 8 
 9         void IPerson.speak(string text)
10         {
11             Console.WriteLine(_name + " say: " + text);
12         }
13 
14         private string _name;
15         string IPerson.name
16         {
17             get
18             {
19                 return _name;
20             }
21             set
22             {
23                 _name = value;
24             }
25         }
26     }
27         static void Main(string[] args)
28         {
29             IPerson person;
30             Console.WriteLine("Main: 通過接口調用方法");
31             person = new Student();
32             person.name = "Nick";
33             person.eat("apple");
34             person.speak("Hello");
35             Console.WriteLine("Main: 通過類調用方法");
36             Student s = new Student();
37             s.name = "Jessice";
38             s.eat("rice");
39             s.speak("Hehe");
40 
41             Console.WriteLine("顯式接口示例");
42             person = new NewStudent(); ;
43             person.name = "Jason";
44             person.eat("Bread");
45             person.speak("Good Luck!");
46 
47             NewStudent ns = new NewStudent();
48             //ns.name = "Lucy";         //報錯,顯式接口只能通過接口來調用
49 
50             Console.ReadLine();
51         }

  運行結果

Main: 通過接口調用方法
Nick eat: apple
Nick say: Hello
Main: 通過類調用方法
Jessice eat: rice
Jessice say: Hehe
顯式接口示例
Jason eat: Bread
Jason say: Good Luck!

  在顯式實現接口時,NewStudent類中對應於IPerson接口的方法(或屬性)名都有IPerson做前綴,而且方法(或屬性)不允許有public、protected等訪問修飾符。當一個類顯式實現接口時,類中用於實現接口的方法只能通過接口

  來調用,而不能通過接口的實例來調用。

 

  接口與抽象類的對比

    接口與抽象類有相似之處,兩者都可以定義一組屬性和方法,都不能被創建實例,只能用作別的類的基類。但接口與抽象類有很大不同之處,如下:

    1、在抽象類中可以定義變量,而在接口中不可以

    2、在抽象類中可以定義構造函數,而接口中不可以

    3、在抽象類中可以定義非公共成員,如protected、private、internal等級的方法變量等,接口中只能定義public的成員

    4、抽象類中的非抽象方法可以有方法體,而接口中的方法只能有定義,不能有實現

    5、由於C#類只能單繼承,所以一旦一個類繼承了某個抽象類,那麼就無法繼承其他抽象類了。也就是說,抽象類的繼承具有唯一性和排他性。而從接口繼承卻不存在這個問題。一個類繼承某個接口,不影響這個類在繼承其他接口

  綜上,在接口中只能定義public訪問級別的方法簽名和屬性簽名,而抽象類除了不能生成類的實例外,其余的行為與普通類相同,能在普通類中定義的所有成員,都可以在抽象類中定義。抽象類中的方法允許定義實現代碼,從而可以

  把派生類中的公共代碼放在抽象類中,實現代碼復用,減少派生類的編碼量。

  接口與抽象類例子如下:

  1     interface IPerson
  2     {
  3         void eat(object food);      //接口的方法
  4         void speak(string text);    //接口的方法
  5 
  6         string name                 //接口的屬性
  7         {
  8             get;
  9             set;
 10         }
 11     }
 12 
 13     public abstract class Person
 14     {
 15         public void eat(object food)
 16         {
 17             Console.WriteLine(name + " eat: " + food.ToString());
 18         }
 19 
 20         public void speak(string text)
 21         {
 22             Console.WriteLine(name + " say: " + text);
 23         }
 24 
 25         private string _name;
 26         public string name
 27         {
 28             get { return _name; }
 29             set { _name = value; }
 30         }
 31     }
 32 
 33     public class Child1:IPerson
 34     {
 35 
 36         public void eat(object food)
 37         {
 38             Console.WriteLine(name + " eat: " + food.ToString());
 39         }
 40 
 41         public void speak(string text)
 42         {
 43             Console.WriteLine(name + " say: " + text);
 44         }
 45 
 46         private string _name;
 47         public string name
 48         {
 49             get
 50             {
 51                 return _name;
 52             }
 53             set
 54             {
 55                 _name = value;
 56             }
 57         }
 58 
 59         public void Study()
 60         {
 61             Console.WriteLine(name + " study hard.....");
 62         }
 63     }
 64 
 65     public class Adult1:IPerson
 66     {
 67         public void eat(object food)
 68         {
 69             Console.WriteLine(name + " eat: " + food.ToString());
 70         }
 71 
 72         public void speak(string text)
 73         {
 74             Console.WriteLine(name + " say: " + text);
 75         }
 76 
 77         private string _name;
 78         public string name
 79         {
 80             get
 81             {
 82                 return _name;
 83             }
 84             set
 85             {
 86                 _name = value;
 87             }
 88         }
 89 
 90         public void Work()
 91         {
 92             Console.WriteLine(name + " work hard....");
 93         }
 94     }
 95 
 96     public class Child2:Person
 97     {
 98         public void Study()
 99         {
100             Console.WriteLine(name + " study hard....");
101         }
102     }
103 
104     public class Adult2:Person
105     {
106         public void Work()
107         {
108             Console.WriteLine(name + " work hard...");
109         }
110     }
111 
112 static void Main(string[] args)
113         {
114             Child1 child1 = new Child1();
115             Child2 child2 = new Child2();
116             Adult1 adult1 = new Adult1();
117             Adult2 adult2 = new Adult2();
118 
119             child1.name = "Jack";
120             child1.eat("apple");
121             child1.speak("hello");
122             child1.Study();
123 
124             adult1.name = "Nick";
125             adult1.eat("apple");
126             adult1.speak("hello");
127             adult1.Work();
128 
129             child2.name = "Lucy";
130             child2.eat("rice");
131             child2.speak("hello");
132             child2.Study();
133 
134             adult2.name = "Lily";
135             adult2.eat("banana");
136             adult2.speak("hello");
137             adult2.Work();
138         }

  運行結果

Jack eat: apple
Jack say: hello
Jack study hard.....
Nick eat: apple
Nick say: hello
Nick work hard....
Lucy eat: rice
Lucy say: hello
Lucy study hard....
Lily eat: banana
Lily say: hello
Lily work hard...

  從Child1和Adult1類的實現代碼來看,兩個類都繼承自IPerson,為了實現接口中定義的方法,相同的代碼在兩個類中寫了兩遍。

  從Person、Child2和Adult2類代碼可以看出,在Person中實現了方法和屬性,不用再派生類中重復實現,實現了代碼的復用。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved