在面向对象编程的过程中,抽象类主要用来进行类型隐藏。我们可以构造出一个固定的一组行为的抽象描述,但是这组行为却能够有任意个可能的具体实现方式。这个抽象描述就是抽象类,而这一组任意个可能的具体实现则表现为所有可能的派生类。模块可以操作一个抽象体。由于模块依赖于一个固定的抽象体,因此它可以是不允许修改的;同时,通过从这个抽象体派生,也可扩展此模块的行为功能。熟悉OCP的读者一定知道,为了能够实现面向对象设计的一个最核心的原则OCP(Open-Closed Principle),抽象类是其中的关键所在。
抽象类不能实例化。抽象类的用途是为多个派生类提供可共享的基类的公共定义。例如,类库可以定义一个作为其多个函数的参数的抽象类,并要求程序员使用该库通过创建派生类来提供自己的类实现。
小天:好了,打住,我明白了。直接告诉我怎么用和注意事项就行了,太过理论的,我现在的水平也听不懂。
老田:好吧,下面代码说明了申明抽象类和抽象方法的语法
public abstract class A //用修饰符abstract将类修饰为抽象类 { //用修饰符abstract将类成员修饰为抽象成员 //注意,抽象方法没有实现体(就是没有方法体) public abstract void GoTo();//用修饰符abstract将类成员修饰为抽象成员 } //继承并实现上面抽象类的派生类 public class B : A { public override void GoTo() //也使用override关键字来实现抽象基类中的抽象方法 { //实现上面抽象方法 } } |
抽象方法没有实现,所以方法定义后面是分号,而不是常规的方法块。抽象类的派生类必须实现所有抽象方法。当抽象类从基类继承虚方法时,抽象类可以使用抽象方法重写该虚方法。例如:
public class D { public virtual void DoWork(int i) { // 这是一个虚方法 } } //用抽象类 E 来继承类 D public abstract class E : D { //下面的抽象方法用重写关键字override来重写基类的虚方法 public abstract override void DoWork(int i); } //普通类 F ,继承抽象类 E public class F : E { public override void DoWork(int i) { //再一次用重写来实现抽象类 E 中的虚方法 } } |
小天:还可以将abstract和override组合起来用啊?那能不能把abstract和virtual组合起来做一个抽象虚方法呢?
老田:第一次听见抽象虚方法这个说法,有创意。不过在抽象方法声明中使用 static 或 virtual 修饰符是错误的。
继承抽象方法的类无法访问该方法的原始实现。在上个示例中,类 F 上的 DoWork 无法调用类 D 上的 DoWork。在此情况下,抽象类可以强制派生类为虚方法提供新的方法实现。
抽象类具有以下特性:
· 抽象类不能实例化。
· 抽象类可以包含抽象方法和抽象属性,也可以包含普通的类成员。
· 只要一个类中有一个抽象方法,那么这个类就必须是抽象类。
· 不能用 sealed修饰符修改抽象类,这意味着抽象类不能被密封。
· 从抽象类派生的非抽象类必须实现全部的抽象方法和抽象属性,包括继承来的。
在方法或属性声明中使用 abstract修饰符以指示方法或属性不包含实现。抽象方法具有以下特性:
· 抽象方法是隐式的虚方法。
· 只允许在抽象类中使用抽象方法声明。
· 因为抽象方法声明不提供实际的实现,所以没有方法体;方法声明只是以一个分号结束,并且在签名后没有大括号 ({ })。
· 实现由一个派生类中的方法来实现,重写的方法用override关键字,此重写方法是非抽象类的一个成员。
· 子类继承抽象父类后,可以使用override关键字覆盖父类中的抽象方法,并做具体的实现。也可以不实现抽象方法,留给后代实现,这时子类仍旧是一个抽象类,必须声明为abstract
· 继承的抽象方法不可以被隐藏。
· 在抽象方法声明中使用 static 或 virtual 修饰符是错误的。
除了在声明和调用语法上不同外,抽象属性的行为与抽象方法一样。
· 在静态属性上使用 abstract修饰符是错误的。
· 在派生类中,通过包括使用 override 修饰符的属性声明,可以重写抽象的继承属性。
最后一个很有必要单独提醒的是,实现抽象方法(在派生类中重写基类的抽象方法)必须与被实现的抽象方法的返回类型、方法名、参数(顺序和类型)都完全相同,不同的是使用的abstract和override这两个关键字的不同。
本文章为天轰穿原创作品,转载请注明出处及作者。
课程地址链接:http://www.ixueyun.com/kcb/02/