[语法]全面理解抽象类(abstract class),抽象方法(abstract method),虚方法(virtual method),接口(interfa
时间:2010-12-05 来源:Jerry Weng
- 一、什么是抽象类?
抽象类是对某一类型的事物,在编程时,为了描述这类事物,而高度抽象、总结出来的一种基础类型。这么说还是很晦涩,打个比方好了,就好比说动物,动物就是一种抽象类,当我们说动物的时候,我们可以想象出很多种具体的动物类别,比如,猪、狗、老虎、狮子,这些都是继承了“动物”这个抽象类而实现了各自特有属性特征的具体子类。
抽象类有几个必要因素:
1、抽象类不能实例化。
2、抽象类可以含有抽象方法和其他带有抽象标志的访问器。(什么是抽象方法,我们接着说。)
3、抽象类是用来给其他类继承的,所以,我们不能用sealed来修饰抽象类,不然就矛盾了。
4、如果抽象类中含有抽象方法或其他带有抽象标志的访问器,在派生自这个抽象类的子类中,必须明确实现这些抽象方法和访问器。
这里有一个来自于MSDN上的例子:
抽象类sample1
abstract class MyBaseC // Abstract class
{
protected int x = 100;
protected int y = 150;
public abstract void MyMethod(); // Abstract method
public abstract int GetX // Abstract property
{
get;
}
public abstract int GetY // Abstract property
{
get;
}
}
class MyDerivedC: MyBaseC
{
public override void MyMethod()
{
x++;
y++;
}
public override int GetX // overriding property
{
get
{
return x+10;
}
}
public override int GetY // overriding property
{
get
{
return y+10;
}
}
public static void Main()
{
MyDerivedC mC = new MyDerivedC();
mC.MyMethod();
Console.WriteLine("x = {0}, y = {1}", mC.GetX, mC.GetY);
}
}
MyBaseC是一个抽象类,因为它有abstract修饰,它含有1个抽象方法MyMethod,注意,因为它是抽象类中的抽象方法,所以我们不需要对它做具体实现,就好比接口中定义的方法一样。它还有两个抽象属性,同样,我们不需要对他们进行具体的实现。
其实从这里,我们其实已经可以看出抽象方法(abstract method)和虚方法(virtual method)的区别了。其实抽象方法是一种隐式的虚方法,只是它的特点是只能在抽象方法中出现和不需要实现具体的方法内容。
MyDerivedC派生自MyBaseC这个抽象类,刚才我们看到的1个抽象方法和2个抽象属性,在这个子类中,我们必须用override来实现它们。
- 二、接口interface的理解。
关于接口的概念,很好说,我也不在这里赘述。关键是如何理解接口。我们可以把接口看作是一种“can do something”的抽象。也打个比方,是个经典的比方,鸟和飞机是两种不同的类别,但是鸟会飞,飞机也会飞,它们都会飞“can fly”,但是他们飞的原理是不同的,但实际他们达到的目的是相同的。所以我们可以写一个飞的接口,让这两个类都实现飞的目的。
为什么要这么做呢?这就是面向对象的编程技巧,我们需要考虑到代码的可读性,扩展性。我们定义了接口,就好比我们订立了一种契约,合同或者说标准。我们必须严格按照这种契约去做事情,正所谓有规矩才成方圆,这样才能更有条理,更有效率地编写代码。
- 三、抽象类和接口取舍建议。
其实,说道这里,都会发现,抽象类和接口在实现某一种方法的机制上面其实是很相似的,都先定立一种条约,然后子类必须实现他们。我们究竟如何使用他们呢,首先看看他们的区别:
- 当我们需要订立的约定内容需要作为参数传递的话,我们就要用接口,抽象类中的抽象方法就不那么方便了。
- 子类只能继承一个抽象类,但是可以继承多个接口。如果我们有一组类需要实现同样的方法,如果用抽象类,那么所有的这些子类的基类都必须是这些抽象类。
- 抽象类可以有具体实现过的方法或者其他成员,但是接口不行,接口中的成员都不可以有具体的实现。
而后这里有几点官方的建议:
- 如果我们希望所写的组件有多个版本,或者说所写的组件需要经常更新,那么建议用抽象类。因为我们可以通过简单的方法来更新基类从而更新我们的组件。但是接口不一样,接口就好比合同,一但订立,就很难去更改。如果我们需要有一个新版本的接口,那么我们需要重新写这个接口。因为我们无法通过更改接口来更新实现这些接口的子类。
- 如果我们所设计的功能可适用于具有相当大差异性的对象们,那么我们建议采用接口。抽象类适用于差异性较小的对象之间所要实现的功能。
- 如果我们需要设计简单的,小型的功能,我们使用接口。如果我们需要设计大型的功能性单元,使用抽象类。
- 如果我们需要提供一种在所有组件中用到的公共的,实现好的功能模块,我们使用抽象类,抽象类可以部分实现成员,但是接口不可以实现任何成员。
综上所述,相信我们对抽象类和接口都能有一个综合性的理解了。今天就写到这里。