C#之美—抽象类与接口孽缘

本文通过生动的故事背景,阐述了抽象类与接口的本质区别。抽象类适用于表现具有明确层次关系的实体,如组织结构和种族;接口则代表了一种契约,规定了必须遵循的行为规范。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在很久很久以前我们的祖先将我们大自然所有能动的物体都定义成“动物”。但是后来在动物的群体当中,有一类动物进化的非常快,它们的智商明显高出其他动物,它们就是“人类”,这也许就是人类文明的起源。

所谓的“人类”开始给动物定义级别了,他们认为“人类”是最聪明的,从而将自己和普通的动物划分界限并且人类是主导“动物”世界的头领。[王清培版权所有,转载请给出署名]

可是大自然总是充满杀戮,大鱼吃小鱼,小鱼吃虾米。这个时候有个很聪明的“人类”动物他想统治全世界,他想来想去如何对这些动物进行管理,怎么让他们能服从于我。所以他进行策划,想法设法的对这些动物进行分析,观察他们的生活习惯,主动的去跟他们交流。他认为不管是什么动物都将有着本质的特性,这些特性是生命的延续也是动物特征的延续。时间不知道过去了多少,他终于总结出一个让一般动物都很难理解的“抽象”动物图。

有了这张图,他得意的不得了。天上飞的我让他们专门去巡逻,陆地上跑的我让他们全天候的伺候我,水里的就跟好玩了,没事出去游游泳。

显然他没有将人类在这张图中体现出来,完全是高度的抽象。我们也不晓得那个人类是怎么想的,按照我们现在的理解,这个人类应该是继承自这个“陆地上的动物”。但是我们现在还不知道他是怎么想的。

他觉得自己是统治者,所以他不会在图中体现出“人类”的描述。他又进行分析了,他认为我该通过某种方式对这些动物进行管理,也就是说不同类型的动物应该有着不同的行为。比如小鸟是会飞的,我必须用笼子把它关起来。鱼是会乱游,也必须有适当的鱼池让它们生成。

他又回去捣鼓管理方式的图了。

这个“人类”看来对管理没什么经验,按照这种管理方式要累死他呢。所有东西都想一手掌控,在一旁的下手可能有点管理的料,他跟头讲:“头,你这样管理他们可能有点不妥,你应该成立专门的管理群体,专门用来管理或者说是研究不同种类的动物”。这句话还真是给这个头子开悟了,头子突然发觉我似乎有跟强大的武器管理这些乱七八糟的动物了。他交代这个下属去好好策划策划然后给他一个管理的组织架构图。

每个皇帝手下都会有那么几个能干的将领,这个下手还真是有学问,他画了一个他的思路图:

这张图再一次给领导头子开了悟,人类既然是动物的统治者,那么就应该对人类的管理组织架构进行抽象。所以他又交代这个下手去考虑考虑画个图给他看看。

领导很喜欢这个图,很清晰的表达出了管理与被管理者之间的界限。两个都有着自己的继承关系,组织机构是针对管理体系的,属于虚拟的继承。而动物的继承体现比较明显点,跟我们的日常生活很像,所以容易理解。通过这个图,思路彻底打开了,要对不同的事务进行归纳抽象,这样才能使事务很清晰很好控制,所谓站的高看的远。[王清培版权所有,转载请给出署名]

 

这个领导就好像成吉思汗,喜欢打仗喜欢征服感,他要征服全世界,要不然上面的那些规划都白费了,得有动物让他管理才行。所有他开始策划组织军队,不管是天上飞的、地上走的、河里游的只要能打仗都可以参军。他开始全身心的设计参军的标准,这个时候我不管你是什么动物,不管你长什么样子,只要符合参军标准就行了。他找来那个下手,跟下手谈论这宏伟的战略目标,并且任手下为军事参谋,辅助他的军事设计和战略目标规划。经过讨论他们得出一个大致的参军标准图:

标准一贴出去,参谋每天都要亲自审核参军者。有这个标准还真方便,基本上来的动物都符合参军标准。军队逐渐成形了,头子要求军事参谋开始设计作战方案。参谋觉得最重要的就是团队配合,要将团队的力量往一处使。所以他开始设计作战时的手语动作。就好比特种兵在作战时的作战计划,通过手语的方式表达。[王清培版权所有,转载请给出署名]

参谋真是高人,又开始画图了:

有了这个作战手语后,参谋开始想看看效果了。寻找了一个附近的岛屿开始进攻了,经过数日的作战后,终于成功的拿下了小岛,小岛的所有动物都受他管理,并且人类也参与了他们的军队开始循环的扩大军队力量。[王清培版权所有,转载请给出署名]

其实说了这么多,目的只有一个,抽象类和接口是有着本质的区别。抽象类体现在群族、组织等一些列有着很明显的层次结构关系的。比如:组织结构、种族、群集。

接口体现某种契约,是必须要遵守的规则,它不用来表现具有继承关系的抽象。比如:生产标准、产品验收标准。所以如果你将接口也视为对类型的抽象是不妥的,接口没有任何实现目的就是为了在面向对象的领域能严格的区分对象和行为的区别。在IL层面上,接口也是抽象的类行为也是虚方法。目的是让我们站在面向对象的角度使用语言,而语言的特性是为了面向对象的概念做支撑。

下面我们来用代码模拟上述的模型,首先是对动物世界的高度抽象,所以我们当然是需要一个抽象类,表示所有动物的基类。


 
  1. /**    
  2.  * author:深度训练    
  3.  * blog:http://wangqingpei557.blog.51cto.com/   
  4.  **/ 
  5. using System;  
  6. using System.Collections.Generic;  
  7. using System.Text;  
  8. using System.Drawing;  
  9.  
  10. namespace ConsoleApplication1  
  11. {  
  12.     /// <summary>  
  13.     /// 动物的顶层抽象  
  14.     /// </summary>  
  15.     public abstract class AnimalBase  
  16.     {  
  17.         /// <summary>  
  18.         /// 动物的肤色  
  19.         /// </summary>  
  20.         public abstract Color Complexion { getset; }  
  21.         /// <summary>  
  22.         /// 动物的身高  
  23.         /// </summary>  
  24.         public abstract int Stature { getset; }  
  25.         /// <summary>  
  26.         /// 动物的体重  
  27.         /// </summary>  
  28.         public abstract int Avoirdupois { getset; }  
  29.         /// <summary>  
  30.         /// 吃饭的动作  
  31.         /// </summary>  
  32.         /// <param name="food">食物对象</param>  
  33.         public abstract void Dining(object food);  
  34.     }  
  35. }  

我定义了两个基本的属性,Complexion肤色、Stature身高,还有一个动作Dining就是吃饭。为什么都是抽象的呢?因为我们的抽象层次很高,不同的动物有着不同的身高、不同的肤色、不同的吃饭习惯。所以都是抽象的,表示后面的派生对象能对基类的成员进行具体化。[王清培版权所有,转载请给出署名]

我们派生一个会飞的动物类:


 
  1. /**    
  2.  * author:深度训练    
  3.  * blog:http://wangqingpei557.blog.51cto.com/   
  4.  **/ 
  5. using System;  
  6. using System.Collections.Generic;  
  7. using System.Text;  
  8.  
  9. namespace ConsoleApplication1  
  10. {  
  11.     /// <summary>  
  12.     /// 会飞的动物基类,但是它的祖先是动物类:AnimalBase  
  13.     /// </summary>  
  14.     public abstract class FlyAnimal : AnimalBase  
  15.     {  
  16.         /// <summary>  
  17.         /// 飞行高度  
  18.         /// </summary>  
  19.         public abstract int FlyHeight { getset; }  
  20.         /// <summary>  
  21.         /// 飞行速度(KM/h)  
  22.         /// </summary>  
  23.         public abstract float FlySpeed { getset; }  
  24.         /// <summary>  
  25.         /// 飞行的行为  
  26.         /// </summary>  
  27.         public void FlyFun()  
  28.         {  
  29.             Console.WriteLine("起飞吧.......");  
  30.         }  
  31.     }  
  32. }  

在继承了AnimalBase之后,FlyAnimal也就是动物了,但是它增添了很多其他的动物色彩,它是一个会飞动物的基类,只要谁继承它了就会飞了,因为它已经具备飞的能力,至于能飞多高要看孕育的怎么样了呵呵,老鹰一定比麻雀飞的高。[王清培版权所有,转载请给出署名]

我们孕育一只老鹰吧,希望我们都飞的更高:


 
  1. /**    
  2.  * author:深度训练    
  3.  * blog:http://wangqingpei557.blog.51cto.com/   
  4.  **/ 
  5. using System;  
  6. using System.Collections.Generic;  
  7. using System.Text;  
  8.  
  9. namespace ConsoleApplication1  
  10. {  
  11.     /// <summary>  
  12.     /// 老鹰,会飞的。  
  13.     /// </summary>  
  14.     public class GledeAnimal : FlyAnimal, JoinArmycorps  
  15.     {  
  16.         private int _flyheight = 1000;  
  17.         /// <summary>  
  18.         /// 飞的高度,最高为1000米  
  19.         /// </summary>  
  20.         public override int FlyHeight  
  21.         {  
  22.             get 
  23.             {  
  24.                 return _flyheight;//能飞1000米高  
  25.             }  
  26.             set 
  27.             {  
  28.                 _flyheight = value; //完全可以控制它飞多高的,要不然后面的仗怎么打啊;  
  29.             }  
  30.         }  
  31.         private float _flyspeed = 100;  
  32.         /// <summary>  
  33.         /// 飞行速度,最快为100KM/h  
  34.         /// </summary>  
  35.         public override float FlySpeed  
  36.         {  
  37.             get 
  38.             {  
  39.                 return _flyspeed;  
  40.             }  
  41.             set 
  42.             {  
  43.                 _flyspeed = value; //当然也是可以控制的  
  44.             }  
  45.         }  
  46.         /// <summary>  
  47.         /// 肤色,我们定义为羽毛颜色  
  48.         /// </summary>  
  49.         public override System.Drawing.Color Complexion  
  50.         {  
  51.             get 
  52.             {  
  53.                 return System.Drawing.Color.Black;  
  54.             }  
  55.             set 
  56.             {  
  57.                 //颜色哪能换啊   
  58.             }  
  59.         }  
  60.         /// <summary>  
  61.         /// 身高,估计也就50CM差不多了  
  62.         /// </summary>  
  63.         public override int Stature  
  64.         {  
  65.             get 
  66.             {  
  67.                 return 50;  
  68.             }  
  69.             set 
  70.             {  
  71.                 //身高似乎可以设置,这里就不支持了。  
  72.             }  
  73.         }  
  74.         /// <summary>  
  75.         /// 体重,估计也就50斤左右吧。  
  76.         /// </summary>  
  77.         public override int Avoirdupois  
  78.         {  
  79.             get 
  80.             {  
  81.                 return 50;  
  82.             }  
  83.             set 
  84.             {  
  85.                 //不会是100斤的。  
  86.             }  
  87.         }  
  88.  
  89.         public override void Dining(object food)  
  90.         {  
  91.             Console.WriteLine("比较喜欢吃:" + food.ToString());  
  92.         }  
  93.  
  94.  
  95.         public bool Take300KgPoleaxe()  
  96.         {  
  97.             return true;  
  98.         }  
  99.  
  100.         public bool Run60MinuteStanding()  
  101.         {  
  102.             return true;  
  103.         }  
  104.     }  
  105. }  

老鹰作为具体的动物,需要实现所有继承下来的抽象成员,唯独一个会飞的行为不需要实现。

继承真是伟大,一生下来就具备了飞行的能力,但是也得多加练习才行。

老鹰听说现在可以参军了,它觉得自己不去参军简直是浪费,老鹰去看看参军要求,觉得可以实现。

军事参谋的参军要求:


 
  1. /**    
  2.  * author:深度训练    
  3.  * blog:http://wangqingpei557.blog.51cto.com/   
  4.  **/ 
  5. using System;  
  6. using System.Collections.Generic;  
  7. using System.Text;  
  8.  
  9. namespace ConsoleApplication1  
  10. {  
  11.     /// <summary>  
  12.     /// 军事参谋贴出来的参军要求  
  13.     /// </summary>  
  14.     public interface JoinArmycorps  
  15.     {  
  16.         /// <summary>  
  17.         /// 身高CM  
  18.         /// </summary>  
  19.         int Stature { getset; }  
  20.         /// <summary>  
  21.         /// 体重KM  
  22.         /// </summary>  
  23.         int Avoirdupois { getset; }  
  24.         /// <summary>  
  25.         /// 是否能拿起300KG中的战斧  
  26.         /// </summary>  
  27.         /// <returns>true:能拿起,false拿不起来</returns>  
  28.         bool Take300KgPoleaxe();  
  29.         /// <summary>  
  30.         /// 快速奔跑持续一小时  
  31.         /// </summary>  
  32.         /// <returns>true:没问题,false歇菜了</returns>  
  33.         bool Run60MinuteStanding();  
  34.     }  
  35. }  

老鹰应该没问题的,它那么厉害;去参谋那里审核了:


 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4.  
  5. namespace ConsoleApplication1  
  6. {  
  7.     class Program  
  8.     {  
  9.         static void Main(string[] args)  
  10.         {  
  11.             //构造老鹰  
  12.             FlyAnimal flyanimal = new GledeAnimal();  
  13.             flyanimal.FlyFun();  
  14.             flyanimal.Dining("兔子肉");//给点兔子肉给你吃  
  15.  
  16.             JoinArmycorps joinarmycorps = flyanimal as JoinArmycorps; //军事参谋准备采用参军标准进行审核  
  17.             if (joinarmycorps.Run60MinuteStanding())  
  18.             {  
  19.                 if (joinarmycorps.Take300KgPoleaxe())  
  20.                 {  
  21.                     if (joinarmycorps.Stature > 170)  
  22.                     {  
  23.                         if (joinarmycorps.Avoirdupois > 80)  
  24.                         {  
  25.                             Console.WriteLine("合格的军人!");  
  26.                         }  
  27.                         else 
  28.                         {  
  29.                             Console.WriteLine("体重不过关!");  
  30.                         }  
  31.                     }  
  32.                     else 
  33.                     {  
  34.                         Console.WriteLine("身高不过关!");  
  35.                     }  
  36.                 }  
  37.             }  
  38.  
  39.             Console.ReadLine();  
  40.         }  
  41.     }  
  42. }  

唉 貌似它体重和身高不够啊 呵呵 不过没关系,我们可以孕育大型的老鹰,完全是为了战争而生的,只需要对老鹰的基因进行培养修改。

总结:其实文章要说明的东西基本上也很清楚了,虽然接口也具备属性和行为,但是它和抽象类是有区别的,这里的参军接口就是一种约定一种规范,老鹰必须必须具备这些因素才行。[王清培版权所有,转载请给出署名]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值