关于抽象类、接口、抽象方法、虚方法
本文系原创
抽象类与接口
抽象类和接口有很多相类似的用法,甚至在某些时候可以相互替换使用,很容易搞混淆,所以在进行抽象类定义时对于abstract class和interface的选择时就比较随意。其实无论是从使用方法还是在设计思想方案来看,二者的区别还是很大的。
先来看看什么是abstract class,C#允许把类和方法声明为abstract,即抽象类和抽象方法。
abstract class通常代表一个抽象概念,提供一个继承的出发点。
在面向对象的概念中,我们知道所有对象都是通过类来描绘的,但是反过来却不一定是这样,并不是所有的类都是用来描绘对象的,如果一个类中没有包含了足够的信息来描绘一个具体的对象,这样的类就是abstract class。abstract class往往用来表达一个我们在对问题领域进行分析、设计中得出的一个抽象概念,是对一些看上去不同但是本质上相同的具体概念的抽象。
比如我们在开一个动物园管理系统时,动物园里动物有猴子、老虎、大象等这样一些具体的对象,猴子、老虎、大象都可以统称为动物,动物就是这样的一个抽象的概念,如果描述一个老虎长什么样子我们都是可以做的到的,如果描述一个动物长什么样子呢,相信谁都做不到,因为现实中不存在这样一个对象。
再看interface,interface是把隐式公共方法和属性组合起来,以封装特定功能的一个集合,一旦实现了interface,类就可以支持interface所指定的所有属性和成员。上面我们先从概念上理解了abstract class和interface,下面我们用一个demo来说明abstract class和interface在使用上的一些特点,在c#中定义抽象类如下:
public abstract class Animal
{
public abstract String GetSountSound();
}
定义接口如下:
public interface IAnimal
{
String GetSountSound();
}
在abstract class的方式中,Animal可以有自己的数据成员,也可以有非抽象的成员方法,而在interface的实现方式中,IAnimal中只能有静态的不能被修改的数据成员,不过在interface中一般不定义数据成员,所有的成员方法都是不包含方法体的。虽然从编程的角度来看,abstract class和interface都可以用来实现面向抽象编程的思想,但是在具体使用上还是有一些区别的。
abstract class在C#中是一个类,是用来被继承的,一个类只能使用一次几成关系;但是一个类可以实现多个interface。其次在abstract class在中是可以有非抽象方法的,而在interface的定义中,所有方法都必须是抽象的,也就是没有方法体的。上面从语法定义和编程的角度我们论述了abstract class在和interface的区别,下面我们从设计理念的层面上分析一下二者的本质区别。前面提到过,abstract class在是被用来继承的,要想使集成关系合理,父类和子类之间必须存在“is a”的关系,即父类和派生类在概念本质上是相同的,对于interface来说则不然,并不要求interface的实现者和interface定义上在概念本质上是一致的,仅仅是实现了interface定义的契约而已。
也就是说:类是对对象的抽象,abstract class在是对类的抽象,interface是对行为的抽象;如果行为跨越了不同类的对象,可使用interface,对于一些相似的类对象,用继承abstract class在;从设计角度讲,abstract class在是从子类中发现了公共的东西,泛化出父类,然后子类继承父类,而interface是根本不知道子类的存在,方法如何实现还不确定,预先定义。
总结几句话来说:
1、abstract class在和interface都不能直接实例化,如果要实例化,abstract class在变量必须指向实现所有抽象方法的子类对象,interface变量必须指向实现所有interfacing方法的类对象。
2、abstract class在要被子类继承,interface要被类实现。
3、interface只能做方法声明,abstract class在中可以做方法声明,也可以做方法实现
4、interface里定义的变量只能是公共的静态的常量,abstract class在中的变量是普通变量。
5、abstract class在里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是abstract class在。同样,一个实现interface的时候,如不能全部实现接口方法,那么该类也只能为abstract class在。
6、抽象方法只能申明,不能实现。abstract void abc();不能写成abstract void abc(){}。
7、abstract class在里可以没有抽象方法
8、如果一个类里有抽象方法,那么这个类只能是abstract class在
9、抽象方法要被实现,所以不能是静态的,也不能是私有的。
10、interface可继承interface,并可多继承interface,但类只能单根继承。
抽象方法与虚方法
抽象方法是只有定义、没有实际方法体的函数,它只能在抽象函数中出现,并且在子类中必须重写;虚方法则有自己的函数体,已经提供了函数实现,但是允许在子类中重写或覆盖。重写的子类虚函数就是被覆盖了。
抽象方法
使用abstract关键字 public abstract bool Withdraw(…);
抽象方法是必须被派生类覆写的方法。
抽象方法是可以看成是没有实现体的虚方法
如果类中包含抽象方法,那么类就必须定义为抽象类,不论是否还包含其它一般方法。
虚方法
使用virtual关键字 public virtual bool Withdraw(…);
调用虚方法,运行时将确定调用对象是什么类的实例,并调用适当的覆写的方法。
虚方法可以有实现体 若一个实例方法的声明中含有 virtual 修饰符,则称该方法为虚拟方法;
一个虚拟方法的实现可以由派生类取代。取代所继承的虚拟方法的实现的过程称为重写该方法;在一个虚拟方法调用中,该调用所涉及的那个实例的运行时类型确定了要被调用的究竟是该方法的哪一个实现。