接口的定义
接口描述的是可属于任何类或结构的一组相关功能,所以实现接口的类或结构必须实现接口定义中指定的接口成员。
接口使用 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 }
这样就可以避免重复写一堆代码,也可以把重心放在处理继承对象的受伤逻辑上,不需要一个一个的根据不同的敌人去触发。
同样玩家也可以继承接口,让不同的敌人可以对玩家造成不同的伤害。
接口可以很好的让玩家与外部物体解耦,不再需要把逻辑细节绑定在玩家身上进行处理。
*** | 以上内容仅为学习参考、学习笔记使用 | ***