前言:本博文讲述了C#面向对象中的抽象类,通过本博文的阅读,读者可以掌握C#抽象类的概念、应用、好处以及一些特性。
一、抽象类概念
- C#允许把类、属性和函数声明为
abstract
。 - 抽象类不能实例化,抽象类可以包含普通属性和抽象属性,普通函数和抽象函数。
- 抽象函数就是只有函数定义没有函数体的函数。显然,抽象函数本身也是虚拟(virtual)的。
注意:类是一个模板,那么抽象类就是一个不完整的模板。我们自然不可以使用不完整的模板去构造对象。
二、示例讲解
1、创建一个鸟类的抽象类
// 鸟的抽象类
abstract class Bird // 含有抽象属性和方法,就一定是抽象类
{
// 鸟速度的属性
public double Speed { get; set; }
// 鸟体重的属性
public abstract double Weight { get; set; }
// 鸟飞翔的抽象方法
public abstract void Fly();
}
当一个类中如果有属性、方法被声明为 abstract
时,这个类也要被声明为 abstract
。
2、创建一个麻雀的类
// 创建麻雀的类,继承自鸟
class Sparrow : Bird // 继承了抽象类,此时必须要求实现抽象属性和方法
{
// 麻雀体重的属性
public override double Weight { get; set; }
// 麻雀飞翔的方法
public override void Fly()
{
Console.WriteLine("麻雀的飞翔~");
}
}
当继承一个抽象类时,必须去实现抽象属性、抽象方法。
3、实例化一个麻雀和鸟
// 用派生类声明和构造
Sparrow sparrow = new Sparrow();
sparrow.Fly();
// 用抽象类声明,用派生类构造
Bird bird = new Sparrow();
bird.Fly();
注意:我们可以通过抽象类去声明对象,但是不可以用抽象类去构造。
4、执行结果,如下所示:
三、抽象类的作用
当我们在写基类时,有的属性、方法是一定要被重写的,在基类中实现并没有意义。这时我们就可以将这种属性、方法写作抽象属性、抽象方法,并将基类改作抽象类,这样我们在写派生类时,直接对没有实现的抽象属性、抽象方法进行重写(override)即可。
四、使用抽象类的好处
抽象类是特殊的类,只是不能被实例化。除此以外,具有类的其他特性;重要的是抽象类可以包括抽象属性、抽象方法,这是普通类所不能的。
- 代码重用,派生类都能用抽象类定义的属性和方法。
- 灵活,某个派生类既可以继承该方法也可以派生一个新的。
- 抽象类是所有派生类通用方法的最小集合,可以封装某一个派生类的实例用来进行传递。
五、抽象类总结
- 抽象类中的抽象属性和抽象方法必须是公有的,因此必须有
public
修饰符。 - 派生类必须重写(override)抽象类中的所有抽象属性和抽象方法,如果没有全部重写(override),那么派生类必须是抽象类。
- 抽象类中可以有非抽象属性和非抽象方法,也可以是私有或者公有,但是如果是私有的话,派生类就不能访问,这样也就无意义了,所以一般情况下都设置为公有。
- 有抽象属性或抽象方法的类一定是抽象类,抽象类中的属性或方法不一定都是抽象的。
六、抽象类与接口的区别
抽象类和接口都包含可以由派生类继承的成员,它们都不能直接实例化。关于接口的知识,请查看:C#接口(Interface)精讲
- 它们的派生类只能继承一个基类(所谓的单继承,多接口继承),即:只能直接继承一个抽象类,但是可以继承任意多个接口。
- 抽象类中可以定义成员的具体实现,但是接口却不行。
- 抽象类中可以包含字段,构造函数,析构函数,静态成员等,接口中不可以。
- 抽象类中的成员可以是私有的(只要它们不是抽象的),受保护的,内部的或者受保护的内部成员,但是接口中的成员必须是公共的(默认就是公共的)。