引子:
时常会有这么一个疑惑,抽象类和接口功能好像,真正用起来该如何抉择呢??
好问题。。
来看看书上怎么说的(C#7.0本质论)
虽然方法可在基类中声明为抽象成员,但是!!如果都从一个基类派生,会用掉唯一的基类机会,(什么意思呢:也就是C#的单继承特性了),所以,什么都往基类里面加,就会显得特别臃肿,且不通用。
所以,原则就是:大共性你给我放基类,小共性用接口。
举个例子:一个动物基类(包含动物叫、动物吃放、动物睡觉) -- 这都没问题!!
但是你给动物的基类里面加一个动物飞行(虽然动物里面的鸟、鸡等都可以飞,但是喵和狗你怎么飞啊),所以,这个加的就很不理智,虽然也是个共性,但是个小共性。
所以,这个小共性用接口实现就非常的Nice,为何呢(因为C#是单继承多接口啊!),也就是说,你的狗子不会飞就不要来接触这个接口咯,会飞的动物,除了继承基类,再加个接口就OK了。
正文:
还是基于游戏,我想到了一个场景,就借这个场景来实战一下吧。
场景描述:
1、三个人(剑士、奶妈、格斗家)组团刷副本
2、三个人的大共性有三条(移动、攻击、聊天)
3、奶妈的可以加团体Buff和团体回血
4、格斗家可以加团体Buff
5、剑士可以加自身Buff
这时候呢:很显然就把移动、打怪、聊天设置为基类了;而剩下的则以接口出现,当然至于为什么要用接口,可以看上一篇关于抽象类的文章,道理差不多。
第一步:先定义一个基类(三个职业共性)
public class Abstract { public abstract class AbstractAction { public abstract void Action(); } public class Move : AbstractAction { public override void Action() { // 英雄移动 Console.WriteLine("正在移动"); } } public class Attack : AbstractAction { public override void Action() { // 英雄攻击 Console.WriteLine("开始打怪"); } } public class Call : AbstractAction { public override void Action() { // 聊天 Console.WriteLine("Hi、妹子..."); } } }
第二部:定义两个接口(回血和加Buff)
interface IAddMilk { void AddMilk(); } interface IAddBuff { void AddBuff(); }
第三部:定义三个英雄
剑士(调用加Buff接口):
public class Swordsman : IAddBuff { private AbstractAction action; public Swordsman() { } public void Select(AbstractAction action) { this.action = action; } public void Go() { action.Action(); } public void AddBuff() { Console.WriteLine("我只给自己加Buff"); } }
格斗家(调用加Buff接口):
public class Fighter : IAddBuff { private AbstractAction action; public Fighter() { } public void Select(AbstractAction action) { this.action = action; } public void Go() { action.Action(); } public void AddBuff() { Console.WriteLine("我给团体加Buff"); } }
奶妈(调用加Buff和加奶接口):
public class Nanny : IAddBuff,IAddMilk { private AbstractAction action; public Nanny() { } public void Select(AbstractAction action) { this.action = action; } public void Go() { action.Action(); } public void AddBuff() { Console.WriteLine("我给团体加Buff"); } public void AddMilk() { Console.WriteLine("我给团体回血"); } }
第四部:实例化三个职业并完成以下功能:
奶妈进图加Buff、加血、顺便和格斗家姑娘打个招呼;格斗家加上团体Buff开始打怪;剑士加上个人Buff开始打怪。
static void Main(string[] args) { // 实例化一个名叫小明的奶妈并进行加Buff和回血,顺便还打了一声招呼 Nanny cat = new Nanny(); Console.WriteLine("我是奶妈小明"); cat.AddBuff(); cat.AddMilk(); cat.Select(new Call()); cat.Go(); Console.WriteLine("------------"); // 实例化一个名叫小强的格斗家,先加个团体Buff,再攻击小怪 Console.WriteLine("我是副C小强"); Fighter SmallC = new Fighter(); SmallC.AddBuff(); SmallC.Select(new Attack()); SmallC.Go(); Console.WriteLine("------------"); // 实例化一个主C小帅,先给自己加个Buff,然后打怪。 Console.WriteLine("我是主C"); Swordsman xuxubaobao = new Swordsman(); xuxubaobao.AddBuff(); xuxubaobao.Select(new Attack()); xuxubaobao.Go(); }
实现:
实验代码:https://github.com/TNever/Interfaceandabstract.git