实例解析C#抽象类
近来有很多童鞋问我有关抽象类的问题,很多初学者不明白为什么要有抽象类,什么情况下使用抽象类。网上搜了下,还真的没多少文章讲此类问题,那么我就在这里简单讲下,鉴于各类书籍、论坛、帖子上有关C#抽象类的语法现象解释的已经足够清楚了,我在这里就只说下抽象类在什么情况下用,举几个例子,并总结了一些C#抽象类的注意要点,供大家参考。
我想大家都打过CS吧!(什么,没打过?拖出去)假如我们现在要开发一个模拟CS的游戏。我们的业务很简单,要求如下:
1、 游戏中要有,一个一次只能持有一支
2、 游戏中有多种支
3、 可以选择支使用
4、 可以开杀人
仅此4条,为了使程序足够简单,能说明我们主要目标就行,所以我们用控制台程序来模拟实现。
方法1
我们先来看第一种实现情况,假设,游戏中现在有手(Pistol)和步(Rifle),那么我们必然需要有对应的两个械的类。
//手类
public class Pistol
{
public void Shoot()
{
Console.WriteLine("手开始射击:叭叭叭");
}
}
//步类
public class Rifle
{
public void Shoot()
{
Console.WriteLine("步开始射击:哒哒哒。。");
}
}
有了械,就可以来实现游戏中的了。业务清单中有一条,匪徒可以选择所用支,那么,我们的类可能就需要实现为下边的情况。
//类
public class Terrorist
{
private Pistol pistol;
private Rifle rifle;
public void SetGun(object gun) //换
{
if (gun is Pistol)
{
pistol = (Pistol)gun; //只能拿一支,在拿手的同时,
rifle = null; 要让步为null
}
else
{
rifle = (Rifle)gun;
pistol = null;
}抽象类的使用
}
public void KillEnemy()
{
Console.WriteLine("开始杀人!");
if (rifle == null)
{
pistol.Shoot();
}
else
{
rifle.Shoot();
}
}
}
如果运行游戏,还需要有个表示层。我们这样来调用这写类:
class Program
{
static void Main(string[] args)
{
Terrorist laDeng = new Terrorist();//new出来一个拉登
laDeng.SetGun(new Pistol());//给他一支手
laDeng.KillEnemy();//拉登开
laDeng.SetGun(new Rifle());
laDeng.KillEnemy();
}
}
好了,程序写到这里就基本实现了我们的业务要求,我们来分析下程序的结构关系,类图是个好的工具,我已经画出来了,请看。
其中,带减号“-”的表示是private的,加号“+”的表示是public的。我们可以发现Terrorist和两个支类Rifle以及Pistol是一种依赖关系。
那么这样实现我们的控制台版的CS游戏好不好呢?
Absolutely不好!!!
假如,游戏上线1个月,我们需要更新支来吸引新老玩家,我们想要增添一款狙击步AWP。好吧,我是一个OO程序员,这难不倒我,我只需要添加一个AWP类:
public class AWP
{
public void Shoot()
{
Console.WriteLine("AWP开始射击:啪。一毙敌");
}
}
然后我们需要修改下Terrorist类,添加一个private字段AWP,然后修改SetGun()方法,
我们需要让if…else变的更长。接下来,还要修改KillEnemy。还是if…else。。。
假如,又过了一个月,我们又想添加一款冲锋M4A1。那么,添加类,修改Terrorist。
假如,又过了一个月。。。。。
Oh my godness!!!你杀了我吧。你会发现,你的代码在不停的修改,如果哪一款械决定删除了,简直要被逼疯了。
那么,好吧,我决定使用抽象类试试
方法2
思考上一个方法,我们的麻烦来自于哪里呢?来自于每一种械都是一个单独的类,她们之间没有任何关联关系,这就使得我们匪徒类Terrorist必须有各个械类型的引用字段,但是。。。业务要求Terrorist一次只能用一支。那么,如果我们能用一个字段来保留这些支的引用就好了。我们设计一个抽象的抢类,让所有的械都继承于这个抽象的类
本着这个思路,我们先画一张新方法的类图。
接下来就是代码实现了。我们先来设计抽象类AbstractGun。
public abstract class AbstractGun
{
public abstract void Shoot();
}
这里代码非常简单,抽象类AbastractGun只有一个抽象方法Shoot()。所有的支类型,都要继承于此抽象类。比如Rifle类
public class Rifle:AbstractGun
{
public override void Shoot()
{
Console.WriteLine("步开始射击:哒哒哒。。");
}
}
这里的每一个子类,都必须override抽象类的Shoot()方法。(这是C#抽象类的语法要求,不懂的拖出去扁。。。)。
下面Terrorist类就简单了。
public class Terrorist
{
private AbstractGun gun;
public Terrorist()
{
}
public void SetGun(AbstractGun gun)
{
this.gun = gun;
}
public void KillEnemy()
{
gun.Shoot();
}
}
再也没有烦人的if…else了,整个世界清静了。。。
那么下边开始游戏,new一个拉登
class Program
{
static void Main(string[] args)
{
Terrorist laDeng = new Terrorist();//new出来一个拉登
laDeng.SetGun(new Pistol());//给他一支手
laDeng.KillEnemy();//拉登开
laDeng.SetGun(new Rifle());
laDeng.KillEnemy();
}
}
如果,哪一天,你需要添加一种械叫机机关(▄︻┳═一)。。。那么,你只需要再写一个机关的类
public class MachineGun:AbstractGun
{
public override void Shoot()
{
Console.WriteLine("机关开始射击:突突突。");
}
}
这时候,你会发现,Terrorist的代码根本无需改动,因为,他需要的的字段只是一个抽象的。
好了,前台立刻可以使用MachineGun了。
laDeng.SetGun(new MachineGun ());
laDeng.KillEnemy();
好了,通过这个例子,我想你已经懂得C#抽象类的使用了。需要注意的是:
1、 抽象类只能被继承,不能实例化,比如你要是想SetGun(new AbstracGun())那就不行。
2、 抽象类中可以包含抽象成员,也可以包含非抽象成员。
3、 但是抽象成员只能出现在抽象类中
4、 抽象方法不能有方法体语句,这单类似于接口,但是接口不能有可访问性修饰符。
5、 抽象方法也可以有参数列表
6、 如果子类不是抽象类,那么子类必须重写(override)抽象方法
7、 子类必须实现父类(抽象类)的所有抽象方法。
就这么多了,希望对大家学习有所帮助
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论