6.2 接口
扫码看视频
如果一个抽象类中所有的方法都是抽象方法,那么可以将该类使用接口来实现。代码6.4的抽象基类Shape只有一个抽象方法draw,因此也可以将Shape定义为接口。
接口使用关键字interface来定义,如代码6.5所示。
接口中所有的方法都是public abstract,因此在声明方法时,可以省略public和abstract这两个说明符。
与public类一样,public接口也必须定义在与接口同名的文件中。
在接口中声明方法时,不能使用native、final、synchronized、protected等说明符。
与继承不同的是,要使用接口,需要编写一个类去实现(使用implements关键字)该接口,并给出接口中所有方法的具体实现。
下面我们编写一个Dog类,实现Animal接口,如代码6.6所示。
如果Dog类只实现了bark方法(读者可以将move方法的实现注释起来),那么在编译时会提示如图6-3所示的错误。
图6-3 实现类、未全部实现接口中的方法而报错
这个错误其实很好理解,接口中所有方法都是抽象的,若编写一个类实现接口,但未全部实现接口中的方法,那么就意味着某些行为是未知的,这样的一个类自然就不允许实例化,编译器要求将这个类声明为抽象的。也就是说,实现一个接口,就实现该接口中所有的方法,如果只是有选择性地实现,那么这个类必须声明为abstract。
下面我们再编写一个类Cat实现Animal接口,如代码6.7所示。
在编译时会提示如图6-4所示的错误。
图6-4 实现接口时方法分配了更低的访问权限而报错
Java要求:在覆盖或实现方法时,覆盖或实现的方法设置的访问权限必须高于或等于被覆盖或被实现的方法的访问权限。方法的访问说明符有4种,其访问权限从高到低依次是:public、protected、default(不加访问说明符时)、private。接口中的所有方法都是public访问权限,因此在实现接口时,方法的访问权限必须设置为public。
读者可自行修改代码6.7,给bark和move方法添加public访问说明符。
接口与抽象类的区别是:接口只是定义了实现它的类应该用什么方法,相当于为类的实现制定了一个规约;而抽象类除了抽象方法外,还可以定义一些方法的默认实现。后面我们会介绍接口更多的用法,你将更清楚接口与抽象类的区别。
题外话 如何在抽象类与接口间取舍呢?当我们需要一个公共实现来简化子类的创建时,使用抽象类就比较合适。如果是对外提供一个统一的操作模型,则使用接口更加合适。当然,抽象类和接口并不是非此即彼的关系,在很多应用中,既有抽象类也有接口。