如果有些方法被调用了,那程序就有问题了,实际上基类的意图是要为所有由它派生出来的类创建一个公共的接口。要创建这种公共接口的唯一原因就是,各个子类要用它自己的方式来实现这个接口。它定义了一个基本的形式,你可以说这是所有的派生类所公有的。还有一种说法,就是基类是一个“抽象的基类或简化为抽象类”。
当你想要通过一个公共的接口来操控一组类的时候,就可以使用抽象类了。通过动态绑定机制,那些符合方法特征的派生类方法将会得到调用。如果方法名同基类的相同,而参数列表不同,那就变成重载了,这大概不是你想要的结构吧。
如果你有一个像Instrument这样的抽象类,那么这种类的对象是没什么意思的。也就是说Instrument只是用来定义接口,而不是具体实现,因此创建Instrument对象没有意义,更何况你还可能要禁止用户这么做。要做到这点,可以让Instrument的方法打印错误信息,但是这样依赖就把问题留到运行时了,因此用户端需要进行详尽的测试。更好的办法还是在编译时发现这个问题。
Java提供了一种被称为抽象方法的机制来解决这个问题。这是一种尚未完成的方法;这种方法只有声明,没有正文。包括抽象方法的类被称为抽象类。如果类包含一个或多个抽象方法,那么这个类就必须被定义成abstract的。否则编译器就会报错了。
既然抽象类是尚未完成的类,那么如果有人想要创建抽象类的对象的话,编译器又打算怎么做呢?编译器没法安全地创建抽象类对象,所以它会报错。由此,编译器保证了抽象类的纯粹性,而你也不用担心它会被误用了。
如果你继承了抽象类,而且还打算创建这个新类的对象,那你就必须实现基类所定义的全部抽象方法。如果你不这么做(你确实可以选择不这么做),那么这个继承下来的类也就成了抽象类了,编译器会强制你用abstract关键词来声明这个类的。
创建一个不包含abstract方法的abstract类,是完全可以的。这种技巧可以用于“不必创建abstract的方法,但是又要禁止别人创建这个类的对象”的场合。Instrument类可以很容易的被修改成abstract类。由于抽象类并不要求它的所有方法都是抽象的,因此只要把几个方法定义成abstract的就行了。