接口的定義
接口描述的是可屬於任何類或結構的一組相關功能,所以實現接口的類或結構必須實現接口定義中指定的接口成員。
接口使用 interface 關鍵字進行定義,可由方法、屬性、事件、索引器或這四種成員類型的任意組合構成。
接口的特性
-
接口類似於抽象基類,不能直接實例化接口;接口中的方法都是抽象方法,實現接口的任何非抽象類型都必須實現接口的所有成員。
-
接口不能包含常量、字段、運算符、實例構造函數、析構函數或類型、不能包含靜態成員。
-
接口成員是自動公開的,且不能包含任何訪問修飾符。
-
接口自身可從多個接口繼承,類和結構可繼承多個接口,但接口不能繼承類。
接口的實現
實現接口可以顯式實現和隱式實現,那么這兩種實現到底有什么區別?
一般情況下,當類或者結構要實現的是單個接口,可以使用隱式實現。
如果類或者結構繼承了多個接口且接口中具有相同名稱的成員時,就要用到顯式實現;當顯式實現方式存在時,隱式實現方式就會失效。
接口的繼承
-
接口繼承和類繼承不同:首先,類繼承不僅是說明繼承,而且也是實現繼承;而接口繼承只是說明繼承。
-
也就是說,派生類可以繼承基類的實現方法,而派生類的接口只繼承了父接口的成員方法說明,沒有繼承父接口的實現。
-
C# 中類繼承只允許單繼承,但是接口繼承允許多繼承,一個字接口可以有多個父接口。
接口的使用(例子)
游戲的場景里我們一般都遇到過一種是不可破壞的物體,一種是可破壞的物體,比如箱子,一擊就碎掉,還有油桶,一碰就爆炸。
那么當用 Unity 來實現游戲交互的時候該怎么做?一般都是通過兩種方式:射線或碰撞。
射線相對來說使用的比較少(因為消耗性能有點多,用的話基本都是常駐場景的射線,非不斷生成的射線),那就只能用碰撞來進行。
我們子彈或者武器碰撞敵人都是通過附加 Collider,那么如何讓子彈或刀劍檢測自己碰撞的物體呢?
我們更多的寫法是這樣的:
1 if (collision.tag == "Enemy") 2 { 3 Enemy enemy = Collision.GetComponent<Enemy>(); 4 }
獲取標簽是否為 Enemy,再獲取腳本 Enemy
如果場景里只有玩家和敵人兩個對象,那毫無疑問這樣的寫法其實是很好的,但問題就在於,一旦以后想添加更多的物體要怎么辦?比如之前說的油桶,箱子,難道要繼續寫更多tag==“油桶/箱子”?后續中還需要添加更多的物體怎么辦? 這樣就會消耗大量的時間在寫代碼,並且需要新建超多的對象(敵人需要新建對象,油桶需要對象,箱子也需要對象),對內存並不友好。這時候能不能讓collider只需要檢測一樣東西,就可以觸發碰撞物體的各種不同效果呢?這下就要使用到接口了。
新建一個腳本,定義接口和接口內的實現方法:
1 public interface IDamage 2 { 3 void Damage(int damage); 4 }
在Enemy腳本中引用,並實現接口:
1 public class Enemy : MonoBehaviour, IDamage 2 { 3 public int Hp = 100; 4 5 public void Damage(int damage) 6 { 7 Hp -= damage; 8 print("受到隨機傷害,扣除" + damage + "健康值!"); 9 if (Hp <= 0) 10 { 11 Destroy(gameObject); 12 } 13 } 14 }
然后只需要給攻擊物體觸發傷害就可以了:
1 public class Attack : MonoBehaviour 2 { 3 private void OnTriggerEnter(Collider collision) 4 { 5 int hp = Random.Range(0, 50); //隨機傷害 6 IDamage idamage = collision.GetComponent<IDamage>(); 7 8 idamage.Damage(hp); 9 } 10 }
這樣就可以避免重復寫一堆代碼,也可以把重心放在處理繼承對象的受傷邏輯上,不需要一個一個的根據不同的敵人去觸發。
同樣玩家也可以繼承接口,讓不同的敵人可以對玩家造成不同的傷害。
接口可以很好的讓玩家與外部物體解耦,不再需要把邏輯細節綁定在玩家身上進行處理。
*** | 以上內容僅為學習參考、學習筆記使用 | ***