這一篇主要來解析關(guān)于面向?qū)ο笾凶羁傄囊粋€概念——接口。
創(chuàng)新互聯(lián)公司是一家集成都做網(wǎng)站、網(wǎng)站制作、網(wǎng)站頁面設(shè)計、網(wǎng)站優(yōu)化SEO優(yōu)化為一體的專業(yè)網(wǎng)站設(shè)計公司,已為成都等多地近百家企業(yè)提供網(wǎng)站建設(shè)服務(wù)。追求良好的瀏覽體驗,以探求精品塑造與理念升華,設(shè)計最適合用戶的網(wǎng)站頁面。 合作只是第一步,服務(wù)才是根本,我們始終堅持講誠信,負(fù)責(zé)任的原則,為您進行細心、貼心、認(rèn)真的服務(wù),與眾多客戶在蓬勃發(fā)展的市場環(huán)境中,互促共生。
對于接口來說,C#是有規(guī)定使用Interface關(guān)鍵字來聲明接口。它的聲明是和類一致的??梢哉f接口就是一個特殊的抽象類。如下代碼:
class Program { static void Main(string[] args) { } } //聲明一個可以飛的接口 interface IRunable { //包含可以被繼承的子類實現(xiàn)的方法 void Run(); }
由以前的抽象類的知識可以知道,抽象類是沒有辦法實例化的(因為含有抽象成員,而抽象成員不含有方法體)。那么接口可不可以實例化呢?答案是肯定的,不能實例化??聪旅娴囊欢未a:
這個時候編譯器告訴我們無法創(chuàng)建抽象類或者接口的實例。
二,接口可以定義哪些成員
1)接口就是一個定義“具有某種能力的抽象類”,既然接口是類,那么它的內(nèi)部可以定義哪些成員呢?
首先,在普通的類中,可以有字段,屬性,方法,索引器,抽象方法等等。那么接口呢?
看下面直接聲明字段,編譯器會報錯,告訴我們接口內(nèi)不能聲明字段
既然接口內(nèi)不能有字段,那也就不存在封裝字段了。所以上邊圖示的封裝字段的代碼也是錯誤的。
同理由上面的代碼也可以知道,在接口中是不可以定義顯式的屬性(因為在屬性中要操作字段賦值,但是字段沒有辦法在接口中聲明)。
那么接口可以聲明自動屬性么?看下面的代碼:
//聲明一個可以飛的接口 interface IRunable { //聲明字段 int nAge { get; set; } string strName { get; set; } ////包含可以被繼承的子類實現(xiàn)的方法 void Run(); }
代碼可以順利編譯通過,那么是為什么呢?這就要看.NET的源碼,我把源碼編譯后的比較結(jié)果如下圖:
抽象方法就不用多了,本來接口就是一個抽象愛類,當(dāng)然可以定義抽象類,但是不在使用abstract關(guān)鍵字,而且方法必須沒有方法體;
2)繼承接口的子類必須實現(xiàn)接口的所有抽象成員。
我們先來看下面的代碼:
//聲明一個接口,其中包含屬性和未實現(xiàn)方法void interface IRunable { string strName { get; set; } void Run(); }
下面來一個實現(xiàn)類,如下:
class Person:IRunable { public void Run() { Console.WriteLine("我可以奔跑!"); } }
這時候,我們編譯,編譯器會告訴我們什么呢?如下圖:
所以繼承接口的類,必須實現(xiàn)接口的所有抽象成員。
正確的代碼如下:
class Person:IRunable { public void Run() { Console.WriteLine("我可以奔跑!"); } public string strName { get { return strName; } set { strName = value; } } }
通過以上的代碼可以發(fā)現(xiàn):
①我們的繼承類在實現(xiàn)接口成員的時候不需要使用override關(guān)鍵字
②實現(xiàn)接口的時候,必須保持簽名一致
由前面抽象類的知識我們有沒有這樣的疑問,什么時候使用抽象類,什么時候使用接口呢?
總結(jié)如下:
①使用抽象類:可以找到父類,并且希望通過父類繼承給子類一些成員
②使用接口:接口就是一個純粹的為了規(guī)范實現(xiàn)的類。比如:多個類具有相同的方法,但是卻找不到父類,就可以將方法定義在接口中。讓這些類去實現(xiàn)。
下面糾紛別來看兩端代碼,比較抽象類和接口的異同,首先是抽象類:
class Program { static void Main(string[] args) { Student s = new Student(); //Student類通過繼承獲得NAge屬性 s.NAge = 10; s.Eat(); Console.WriteLine("--------Student和Worker類分別通過繼承獲得了父類的非私有成員,實現(xiàn)了父類的抽象方法--------"); Worker w = new Worker(); //Worker類通過繼承獲得NAge屬性 w.NAge = 40; w.Eat(); Console.ReadKey(); } } //定義父類 abstract class Person { private int nAge; public int NAge { get { return nAge; } set { nAge = value; } } private void Run() { Console.WriteLine("我是父類,我可以跑!"); } public abstract void Eat(); } class Student : Person { //子類覆寫了父類的抽象方法 public override void Eat() { Console.WriteLine("我是子類,我繼承了父類,我可以在學(xué)校吃飯!"); } } class Worker:Person { //同樣Worker也通過繼承獲得了父類的非私有成員 public override void Eat() { Console.WriteLine("我是子類,我繼承父類,我可以在工廠吃飯"); } }
接下來,來看看接口是怎么規(guī)范多個類的實現(xiàn)的。
class Program { static void Main(string[] args) { Student s = new Student(); s.strName = "小學(xué)生"; s.Run(); Console.WriteLine(s.strName); Console.WriteLine("--------------------"); Worker w = new Worker(); w.strName = "看我能不能瀆職"; w.Run(); Console.WriteLine(w.strName); Console.ReadKey(); } } interface IRunable { //規(guī)范子類必須實現(xiàn)strName屬性 string strName { get; set; } //規(guī)范子類必須實現(xiàn)Run()方法 void Run(); } class Student:IRunable { //這里是子類的字段 string strname; public string strName { get { return strname; } set { strname = value; } } public void Run() { Console.WriteLine("我是小學(xué)生,我在學(xué)校里面跑步!"); } } class Worker:IRunable { string strname; public string strName { get { return "工人"; } set { strname = value; } } public void Run() { Console.WriteLine( "我是工人,我需要在廠區(qū)跑!"); } }
由以上的代碼可不可以發(fā)現(xiàn),接口僅僅在規(guī)定一個規(guī)范子類的實現(xiàn),而抽象類可以通過繼承,繼承給子類某些成員。
最后來看一下,接口的顯示實現(xiàn),我先看接口的普通實現(xiàn)(以上的代碼實現(xiàn)接口的方式都是隱式實現(xiàn))
interface IRunable { //規(guī)范子類必須實現(xiàn)strName屬性 string strName { get; set; } //規(guī)范子類必須實現(xiàn)Run()方法 void Run(); } class Student:IRunable { //這里是子類的字段 string strname; public string strName { get { return strname; } set { strname = value; } } public void Run() { Console.WriteLine("我是小學(xué)生,我在學(xué)校里面跑步!"); } }
顯式實現(xiàn)接口
class Student:IRunable { //這里是子類的字段 string strname; //顯示實現(xiàn)接口 string IRunable.strName { get { return strname; } set { strname = value; } } void IRunable.Run() { Console.WriteLine("我是小學(xué)生,我在學(xué)校里面跑步!"); } }
顯示的實現(xiàn)接口是為了解決方法名沖突的問題。但是顯示實現(xiàn)接口會出現(xiàn),在上面的代碼中會出現(xiàn)一個問題,如下圖:
為什么會這樣呢?
因為顯式實現(xiàn)接口的方法是私有的,不能通過對象變量來調(diào)用。那應(yīng)該怎么調(diào)用呢,看下面的代碼:
class Program { static void Main(string[] args) { //里氏替換原則,父類變量指向子類對象,并通過父類變量調(diào)用子類方法 IRunable ir = new Student(); ir.Run(); Console.ReadKey(); } } interface IRunable { //規(guī)范子類必須實現(xiàn)strName屬性 string strName { get; set; } //規(guī)范子類必須實現(xiàn)Run()方法 void Run(); } class Student:IRunable { //這里是子類的字段 string strname; //顯示實現(xiàn)接口 string IRunable.strName { get { return strname; } set { strname = value; } } void IRunable.Run() { Console.WriteLine("我是小學(xué)生,我在學(xué)校里面跑步!"); } // Student s = new Student(); }
打印結(jié)果如下:
顯式實現(xiàn)接口,這個接口的方法,只能通過接口變量來調(diào)用。
接口導(dǎo)圖總結(jié)如下:
如果您覺得不錯,點擊右下角贊一下吧!您的支持,是我寫作的動力!
畢業(yè)實習(xí)交流群:221376964。你也可以關(guān)注我的新浪微博進行交流。