朋友曾问我抽象类是否至少要有一个抽象方法,我查了很多资料,结果都是:“抽象类允许(但不要求)抽象类包含抽象成员”。但是一个抽象类里不写抽象方法就没有意义了,既然如此,还不如直接写个普通类? 在一个抽象类里可以不声明抽象方法,这在语法上是没问题的,但实际来说,这样是没有任何意义的。也就是说,你为什么会选择写一个抽象类呢?当然是为了想某个方法能够被OVERRIDE,以实现多态。后来查找MSDN结果如下:
abstract 修饰符可以和类、方法、属性、索引器及事件一起使用。
在类声明中使用 abstract 修饰符以指示类只能是其他类的基类。
抽象类具有以下特性:
- 抽象类不能实例化。
- 抽象类可以包含抽象方法和抽象访问器。
- 不能用 sealed 修饰符修改抽象类,这意味着该类不能被继承。
- 从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实实现。
在方法或属性声明中使用 abstract 修饰符以指示此方法或属性不包含实现。
抽象方法具有以下特性:
- 抽象方法是隐式的 virtual 方法。
- 只允许在抽象类中使用抽象方法声明。
- 因为抽象方法声明不提供实实现,所以没有方法体;方法声明只是以一个分号结束,并且在签名后没有大括号 ({ })。例如:
public abstract void MyMethod();
- 实现由 overriding 方法提供,它是非抽象类的成员。
- 在抽象方法声明中使用 static 或 virtual 修饰符是错误的。
除了在声明和调用语法上不同外,抽象属性的行为与抽象方法一样。
抽象类必须为所有接口成员提供实现。
MSDN中C#语言规范的:10.1.1.1抽象类。此文如下:
abstract
修饰符用于表示所修饰的类是不完整的,并且它只能用作基类。抽象类与非抽象类在以下方面是不同的:
- 抽象类不能直接实例化,并且对抽象类使用
new
运算符是编译时错误。虽然一些变量和值在编译时的类型可以是抽象的,但是这样的变量和值必须或者为null
,或者含有对非抽象类的实例的引用(此非抽象类是从抽象类派生的)。 - 允许(但不要求)抽象类包含抽象成员。
- 抽象类不能被密封。
当从抽象类派生非抽象类时,这些非抽象类必须具体实现所继承的所有抽象成员,从而重写那些抽象成员。在下面的示例中
1 abstract class A
2 {
3public abstract void F();
4}
5 abstract class B: A
6 {
7public void G() {}
8}
9 class C: B
10 {
11public override void F() {
12// actual implementation of F
13}
14}
抽象类 A
引入抽象方法 F
。类 B
引入另一个方法 G
,但由于它不提供 F
的实现,B
也必须声明为抽象类。类 C
重写 F
,并提供一个具体实现。由于 C
中没有了抽象成员,因此可以(但并非必须)将 C
声明为非抽象类。
有关抽象类和抽象方法的问题,我个人也做了一些总结,如下:
§ abstract关键字用于将类指定为抽象类,这些抽象类可以派生出其他类。
a. 一个抽象类可以同时包含抽象方法和非抽象方法。
b. 抽象方法的目的在于指定派生类必须实现与这一方法关联的行为。
c. 抽象方法只在派生类中真正实现,这表明抽象方法只存放函数原型(方法的返回类型,使用的名称及参数),而不涉及主体代码。
d. 如果父类被声明为抽象类,并存在未实现的抽象方法,那么子类就必须实现父类中所有的abstract成员,除非该类也是抽象的。
例如:
1 abstract class A说明: 抽象类
2 {
3 public abstract void F();
4}
5
6 abstract class B: A
7 {
8 public void G()
9 {}
10}
11
12 class C: B
13 {
14 public override void F()
15 {
16 // actual implementation of F
17 }
18}
19
20A
引入抽象方法F
。类B
引入另一个方法G
,但由于它不提供F
的实现,B
也必须声明为抽象类。类C
重写F
,并提供一个具体实现。由于C
中没有了抽象成员,因此可以(但并非必须)将C
声明为非抽象类。
e. 抽象类不能被实例化,使用override关键字可在派生类中实现抽象方法,经override声明重写的方法,其签名必须与override方法的签名一致。