3.3 接口
在本章前面的内容中已经介绍过,Java只允许单继承,即不允许一个类同时继承多个父类,不过Java中提供了接口,一个类可以同时实现很多个接口,这样就实现了多重继承的部分功能。
3.3.1 接口的定义
接口的定义包括接口声明和接口体。其定义的一般格式如下:
[public] interface interfaceName[extends listOfSuperInterface] { type methodname(parameterlist); type constname=value; }
其中,接口只能用public限制访问修饰符修饰,不能使用其他的限制访问修饰符,extends后可以有多个父接口,这多个父接口之间用逗号隔开。
接口体包括常量定义和方法声明,这里的方法声明包含方法名称、参数列表和返回值类型,但是没有方法体。看到这里,读者可能会问,接口不就是抽象类吗?的确,接口与抽象类有许多相同之处,但是它们之间也有很多的不同点。接口与抽象类是属于不同的层次,接口是将抽象类提高了一个层次,并给它加上了一些限制和特性。
下面来比较一下接口与抽象类的异同。
相同点:
❑ 接口与抽象类中都包含有方法声明,这些方法声明将在实现接口或继承抽象类的类中具体实现,否则这些实现接口或继承抽象类的类还是抽象类。这也是容易把接口和抽象类混淆的主要原因。
❑ 接口与抽象类中由于都有方法声明,因此都不能用new来创建对象,但它们都可以去引用实现接口或继承抽象类的类的实例。
❑ 接口与抽象类都可以实现继承,继承之后子接口就拥有了所有父接口中的方法声明和常量定义了,抽象类继承父类后也将用于父类中的所有方法和属性。
不同点:
❑ 在抽象类中,方法声明的前面必须加上abstract关键字,而在接口中则不需要。
❑ 在抽象类中,除了抽象方法之外,也可以定义普通的成员方法和成员变量,而在接口中这是不允许的,接口中只能有方法声明和常量定义,这是接口和抽象类的本质区别。
❑ 接口允许多继承,不但一个接口可以继承多个父接口,而且实现接口的类也可以同时实现多个接口。
【实例3-9】接口的定义。该实例定义一个用于计算立体几何图形体积的接口,因为不同的立体几何图形计算体积的方法不同,因此可以在接口中定义一个计算体积的方法的声明,而在具体的图形类中实现该接口,并根据各图形的体积计算公式来定义该方法。接口的具体定义如下:
01 public interface ThreeD_Object { 02 float Volume(float x, float y, float z);//定义接口中的抽象方法 03 }
【代码说明】在该接口的第2行定义了一个抽象方法Volume。
说明
在接口中只能有方法声明,不能有方法的具体实现。
3.3.2 接口的实现
接口中的方法声明需要在某个类中定义实际的代码,这时我们就称这个类“实现”了这个接口。关键字implements用来表示对接口的实现。如果一个类同时实现了多个接口,则只需在implements后把多个接口名用逗号隔开即可。
接口实现的一般格式如下:
class <类名> implements <接口名>
例如,下面示例代码中定义了两个接口及实现这两个接口的实现类。
01 interface A { 02 void Method1(); 03 } 04 interface B { 05 void Method2(); 06 } 07 class C implements A,B { 08 public void Method1() { 09 ……//具体方法定义代码 10 } 11 public void Method2() { 12 ……//具体方法定义代码 13 } 14 }
【代码说明】在第8行实现了接口A中的方法,第12行实现了接口B中的方法。
说明
在类中实现接口中的方法声明时,方法的返回值类型、方法名称和参数列表必须保持一致,同时要给出方法的具体实现代码。此外,Java中规定在类中实现的方法都要声明为public的。
如果在实现接口的类中没有定义接口中方法的具体实现,那么在这个类中这个方法就将是一个抽象方法,由于这时它位于类中,那么这个类就将成为抽象类。
【实例3-10】接口的实现。
在实例3-9中定义了用于计算立体几何图形体积的接口,在实例3-10中根据具体立体几何图形分别定义该接口不同的实现类。
首先定义立方体的实现类Cube,具体代码如下:
01 class Cube implements ThreeD_Object { 02 //根据立方体体积计算公式具体定义方法 03 public float Volume(float x, float y, float z) { 04 return x*y*z; 05 } 06 }
【代码说明】在第3行定义了ThreeD_Object接口中声明的Volume()方法,在该方法中具体定义了立方体体积的计算方法。
然后定义圆柱体的实现类Cylinder,具体代码如下:
01 class Cylinder implements ThreeD_Object { 02 //根据圆柱体体积计算公式具体定义方法 03 public float Volume(float x, float y, float z) { 04 return x*y*y *z; 05 } 06 }
【代码说明】在第3行定义了ThreeD_Object接口中声明的Volume()方法。在该方法中具体定义了圆柱体体积的计算方法。
最后定义应用程序类ShowVolume,用来测试实现接口的类,其具体代码定义如下:
01 public class ShowVolume { 02 public static void main(String args[]){ 03 float vol1,vol2; 04 float PI=3.14159f; 05 ThreeD_Object obj1=new Cube(); //创建Cube类的对象 06 ThreeD_Object obj2=new Cylinder() ;//创建Cylinder类的对象 07 vol1=obj1.Volume(20.0f, 10.0f, 30.0f); //调用Cube类中实现的接口中的方法 08 vol2=obj2.Volume(PI, 10.0f, 30.0f); //调用Cylinder类中实现的接口中的方法 09 System.out.println("The Volume of cube is:"+vol1); 10 System.out.println("The Volume of cylinder is:"+vol2); 11 } 12 }
【代码说明】在应用程序类中的第5行和第6行分别实例化一个Cube类和Cylinder类的实例,然后在第7行和第8行通过这两个实例分别调用了Volume()方法,虽然是同一个方法,但是这两个方法在不同的类中得到了不同的定义。
【运行结果】最终程序输出结果如图3.6所示。
图3.6 接口实现类中具体方法的执行结果