在我们所有乐器(Instrument)例子中基础类Instrument内的方法都肯定是伪方法若去调用这些方法就会出现错误那是由于Instrument的意图是为从它衍生出去的所有类都创建一个通用接口 之所以要建立这个通用接口唯一的原因就是它能为不同的子类型作出不同的表示它为我们建立了一种基本形式使我们能定义在所有衍生类里通用的一些东西为阐述这个观念另一个方法是把Instrument称为抽象基础类(简称抽象类)若想通过该通用接口处理一系列类就需要创建一个抽象类对所有与基础类声明的签名相符的衍生类方法都可以通过动态绑定机制进行调用(然而正如上一节指出的那样如果方法名与基础类相同但自变量或参数不同就会出现过载现象那或许并非我们所愿意的) 如果有一个象Instrument那样的抽象类那个类的对象几乎肯定没有什么意义换言之Instrument的作用仅仅是表达接口而不是表达一些具体的实施细节所以创建一个Instrument对象是没有意义的而且我们通常都应禁止用户那样做为达到这个目的可令Instrument内的所有方法都显示出错消息但这样做会延迟信息到运行期并要求在用户那一面进行彻底可靠的测试无论如何最好的方法都是在编译期间捕捉到问题 针对这个问题Java专门提供了一种机制名为抽象方法它属于一种不完整的方法只含有一个声明没有方法主体下面是抽象方法声明时采用的语法 abstract void X(); 包含了抽象方法的一个类叫作抽象类如果一个类里包含了一个或多个抽象方法类就必须指定成abstract(抽象)否则编译器会向我们报告一条出错消息 若一个抽象类是不完整的那么一旦有人试图生成那个类的一个对象编译器又会采取什么行动呢?由于不能安全地为一个抽象类创建属于它的对象所以会从编译器那里获得一条出错提示通过这种方法编译器可保证抽象类的纯洁性我们不必担心会误用它 如果从一个抽象类继承而且想生成新类型的一个对象就必须为基础类中的所有抽象方法提供方法定义如果不这样做(完全可以选择不做)则衍生类也会是抽象的而且编译器会强迫我们用abstract关键字标志那个类的抽象本质 即使不包括任何abstract方法亦可将一个类声明成抽象类如果一个类没必要拥有任何抽象方法而且我们想禁止那个类的所有实例这种能力就会显得非常有用 Instrument类可很轻松地转换成一个抽象类只有其中一部分方法会变成抽象方法因为使一个类抽象以后并不会强迫我们将它的所有方法都同时变成抽象下面是它看起来的样子 下面是我们修改过的管弦乐器例子其中采用了抽象类以及方法 //: Musicjava // Abstract classes and methods import javautil*; abstract class Instrument { int i; // storage allocated for each public abstract void play(); public String what() { return Instrument; } public abstract void adjust(); } class Wind extends Instrument { public void play() { Systemoutprintln(Windplay()); } public String what() { return Wind; } public void adjust() {} } class Percussion extends Instrument { public void play() { Systemoutprintln(Percussionplay()); } public String what() { return Percussion; } public void adjust() {} } class Stringed extends Instrument { public void play() { Systemoutprintln(Stringedplay()); } public String what() { return Stringed; } public void adjust() {} } class Brass extends Wind { public void play() { Systemoutprintln(Brassplay()); } public void adjust() { Systemoutprintln(Brassadjust()); } } class Woodwind extends Wind { public void play() { Systemoutprintln(Woodwindplay()); } public String what() { return Woodwind; } } public class Music { // Doesnt care about type so new types // added to the system still work right: static void tune(Instrument i) { // iplay(); } static void tuneAll(Instrument[] e) { for(int i = ; i < e.length; i++) tune(e[i]); } public static void main(String[] args) { Instrument4[] orchestra = new Instrument4[5]; int i = 0; // Upcasting during addition to the array: orchestra[i++] = new Wind4(); orchestra[i++] = new Percussion4(); orchestra[i++] = new Stringed4(); orchestra[i++] = new Brass4(); orchestra[i++] = new Woodwind4(); tuneAll(orchestra); } } ///:~ 可以看出,除基础类以外,实际并没有进行什么改变。TW.winGWit.Com 创建抽象类和方法有时对我们非常有用,因为它们使一个类的抽象变成明显的事实,可明确告诉用户和编译器自己打算如何用它。 |