我們都知道虛方法實現多態,抽象方法實現多態等,我們今天來看看如何使用接口實現多態
1.首先我們先要來了解了解什麼是接口,它存在的意識
01.接口就是為了約束方法的格式(參數和返回值類型)而存在的
02.接口可以實現多繼承,彌補單繼承的缺陷。
03.接口可以看成是一個特殊的抽象類,通過反編譯看源碼可知
04.接口中方法不用訪問修飾符,因為CLR會自動添加,並且不能有方法體
05.如果一個類實現了某個接口,就得實現該接口中所有的方法
06.接口要謹慎使用,防止出現接口污染!
07.接口僅僅代表一種能力,實現該接口的類和接口沒有繼承關系
08.接口是用來實現的,類是用來繼承的。
09.其實很多時候,看似可以不用接口,因為接口就是一個方法的約定,
表明你這個類必須要有某些方法,但是不寫接口也可以有這些方法,用了接口,
就可以使用接口變量,統一調用,實現多態
10.接口中只能定義方法,不能定義變量。
2.抽象類和接口的區別:
當需要的各個對象之間存在父子類關系時,可以考慮使用抽象類,
當各個對象之間不存在繼承關系,只是有相同的能力時,而已考慮使用接口
3.接口的通俗理解
01.飛機會飛,鳥會飛,他們都繼承了同一個接口“飛”;但是F22屬於飛機抽象類,
鴿子屬於鳥抽象類。
02.就像鐵門木門都是門(抽象類),你想要個門我給不了(不能實例化),
但我可以給你個具體的鐵門或木門(多態);而且只能是門,你不能說它是窗(單繼承);
一個門可以有鎖(接口)也可以有門鈴(多實現)。
門(抽象類)定義了你是什麼,接口(鎖)規定了你能做什麼
(一個接口最好只能做一件事,你不能要求鎖也能發出聲音吧(接口污染))
下面我們舉個用接口實現多態的例子:
01.新建一個飛的接口
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 接口 { //飛的接口 public interface IFly { //接口中方法不用訪問修飾符,因為CLR會自動添加,並且不能有方法體 void Say(); } }
02.創建一個吃的接口
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 接口 { //吃的接口 public interface IEat { //接口中方法不用訪問修飾符,因為CLR會自動添加,並且不能有方法體 void eat(); } }
03.創建一個鳥類來實現飛的接口和吃的接口
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 接口 { //鳥實現飛的接口和吃的接口 public class Grid:IFly,IEat //注意 接口:接口叫繼承 ,類:接口叫實現 { //如果一個類實現了某個接口,就得實現該接口中所有的方法 public void Say() { Console.WriteLine("鳥在飛"); } public void eat() { Console.WriteLine("鳥在吃"); } } }
04.創建一個飛機類實現飛的接口
using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 接口 { //飛機實現飛的接口 public class Plan:IFly { public void Say() { Console.WriteLine("飛機在飛"); } } }
05.在Main方法實現調用
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 接口 { class Program { static void Main(string[] args) { //定義飛接口數組實例化對象 IFly[] iFlies = { new Grid(), new Plan() }; //循環數組調用方法實現多態 foreach (IFly iFly in iFlies) { iFly.Say(); } //鳥吃實例化對象 IEat iEats = new Grid(); //調用方法實現多態 iEats.eat(); Console.ReadLine(); } } }
這樣就可實現多態了,運行結果如下:
注:如果有一個類要實現兩個接口,不巧的是這兩個接口(如:IFly,IPlay)中右兩個同命名的方法(Eat)
我們都知道
如果一個類實現了某個接口,就得實現該接口中所有的方法
這怎麼辦吶?自有解決的方法的:
我們就可以使用接口名.方法來實現
//實現了IFly和IPlay兩個接口,但兩個接口中都有Eat方法 public class Dog:IFly,IPlay { //如果一個類實現了某個接口,就得實現該接口中所有的方法 //這樣我們就可以使用接口名.方法來實現 void IFly.Eat() { } void IPlay.Eat() { } }
4.接口總結(摘錄):
接口是組件之間的協議,描述了組件對外提供的服務。從技術上講接口是一組包含了函數型方法的數據結構。 通過這組數據結構,客戶代碼可以調用組件對象的功能。接口可以從父接口中繼承。接口的繼承首先是說明性繼承,不是實現性繼承,它的實現需要通過類或結構來實現;其次接口繼承可以是多繼承。
屬性的本質是方法,索引器的本質是屬性。
接口包含的成員有方法、屬性、索引指示器和事件。由於接口允許多繼承,在可能發生二義性的地方可以采用全權名來避免。可以用類來實現接口。在類中定位接口成員的實現稱之為接口映射。類必須為接口的所有成員提供具體的實現,包括接口中顯式定義的成員, 以及接口從父接口中繼承而來的成員。同樣,在對接口的實現過程中可以采用顯式接口成員執行體來避免產生二義性。派生類可以對基類已經實現的接口進行重實現。
抽象類也可以實現接口,但接口成員必須映射到抽象類的抽象成員。抽象類的派生類如果是非抽象類,則必須通過方法重載來實現接口成員。