这几个月使用Lua进行开发,对C#方面的内容久放后,实在是疏离了不少,这两天终于闲下来,打算重拾C#,不过在使用了Lua这种轻量级的脚本语言一段时间后,通过其模仿高级语言的生态,让我对C#的高级语言特性也明白了不少,特此做一个小小的总结。
什么是继承?在Lua中是通过元表这个非常强大的语言特性进行模拟继承特性的,简述其原理就是:将特定的“子表”的元表设置为其“父表”,这样的话,通过元表的特性,当调用某方法或属性时,在“子表”中无法找到该属性变量时,就会通过元表索引到其“父表”中查找。所以其表现的实质就是:子表复制了一份父表的属性和方法。
好了,通过这种方式就可以解释什么是继承了:Is-A ,某个类为什么要派生自其父类?因为它需要其父类的属性或方法,这个父类应该是高度概括了某种事物应该具备的共性,就像说什么是人类?能使用工具、有头有手有脚......一大堆特性聚合体的生物,然后其派生类男性人类、女性人类都应该具备这些基本的特性。
继承不可乱用的原因在哪?
那就是因为派生类在其派生的时候(实例化出派生类的对象),会完整的复制一份父类的所有属性与方法(这就是Lua通过元表能模拟出的强大特性)。就像人类从胚胎发育成幼儿,其需要复制一份通用的数据:头啊、四肢、躯干等等,直到其需要派生的部分出现,然后实例化其派生类所拥有的特性:男性丁丁啊之类的。这就是一个继承过程。(在此对计算机大佬们拜服。)
这时候就想想,如果这份人类数据并不是高度精炼,高度通用的话,会出现什么事呢?我们不妨假设这份人类数据里,共性中包含丁丁(并不是我粗俗...实在是不知道其他有啥特别明显的特征。),那么这就十分恐怖了,人类说玩完儿了也不过分。而在代码世界中,这种情况可能不会导致严重的后果,但是也是一件十分糟糕的事情,或许我们平时个人开发,或者项目规模比较小的时候不觉得,如果某个冗余的基类派生了成千上万个类,而起派生类又实例化了成千上万个对象。那么那些冗余的数据可能就会有上百万份同时存在的可能,光是想想就为运行设备捏了把冷汗。
所以继承必须慎之又慎,我们可能做不到大佬那样在动手写之前就考虑的周道万分,但是在开发过程中,要不断的重构代码和精简设计,很多优秀的设计其实都是重构才产生出来的,并不是一定框架用终身,而是不断调整框架适用实际需求的。
多态性的核心体现其实就是通过声明其父类,然后通过父类的通用特性来在运行过程中再决定其具体实现该特性的对象。比如说,某超市为了推销他们的产品,现在要招100个人来试吃某产品。(人就是父类,超市需要的是人这个群体来试吃,他们并不会管这个人是男人(派生类)、女人(派生类)、小男孩(男人的派生类)等等具体的属性,重要的是这些派生类都拥有父类人的共性(吃)这个能力就行了。)
然后在试吃现场,超市就调用了这个类(人)的实例化方法(现场招募),然后让这些对象(试吃群众)调用他们自身的共性方法(吃),表现出多态性(吃的方式不同,吃的数量也不同.....)
接口,在我的理解中,他就像是一份协议、或者说职业声明一样(0.0形象化比较好理解),他规定了一个职业应该具备哪些条件(属性),哪些技能(方法)。比如说假定成为护士的协议(接口)为:20岁以上、50岁以下、性别为女、且掌握护理学、临床医学等等诸多技能。那么这就规定好了一个护士的标准,进行了标准化和规范化。这样在某个医院需要在派遣某些护士去处理事情的时候,就不用特别考虑这个护士是不是掌握了护理学,或者她是不是女性人类。因为这些都是事先规定好的,且必须实现的。(接口中并没有具体实现,而继承它的子类,必须对那些接口规定的属性和方法有具体的实现)
在C#中,因为类的继承具备单根性,也就是说每个类只能继承自一个父类,而不是像C++一样可以多重继承。接口就是对这种强大的功能特性进行的一种补充模仿,类可以继承多个接口,通过接口实现了多重继承,我们就能同样便捷的使用其多态性,来精简我们的代码,优雅的实现一些功能。
其多态性的体现与继承一致,或者说它就是精简的、不复制属性和方法的继承。因此不再赘述。
C#中是通过了两种方法来实现:1、函数重载。2、运算符重载。(因为比较简单,不赘述)
C#中是通过了两种方式来实现:1、抽象类。 2、虚方法(这一点就是通过virtual关键字,部分定义必须在派生类中具体实现的方法(必要条件)。可以理解为,作为一个人他的必要条件是呼吸,那么派生类男人女人们必须拥有自己的呼吸方式,而不能不呼吸(实现))