用关键字interface,你可以从类的实现中抽象一个类的接口。也就是说,用interface,你可以指定一个类必须做什么,而不是规定它如何去做。接口在语句构成上与类相似,但是它们缺少实例变量,而且它们定义的方法是不含方法体的。实际上,这意味着你可以定义不用假设它们怎样实现的接口。一旦接口被定义,任何类成员可以实现一个接口。而且,一个类可以实现多个接口。
要实现一个接口,接口定义的类必须创建完整的一套方法。然而,每个类都可以自由的决定它们自己实现的细节。通过提供interface关键字,Java允许你充分利用多态性的“一个接口,多个方法”。
接口是为支持运行时动态方法解决而设计的。通常,为使一个方法可以在类间调用,两个类都必须出现在编译时间里,以便Java编译器可以检查以确保方法特殊是兼容的。这个需求导致了一个静态的不可扩展的类环境。在一个系统中不可避免会出现这类情况,函数在类层次中越堆越高以致该机制可以为越来越多的子类可用。接口的设计避免了这个问题。它们把方法或方法系列的定义从类层次中分开。因为接口是在和类不同的层次中,与类层次无关的类实现相同的接口是可行的。这是实现接口的真正原因所在。
注意:接口增添了很多应用程序所需的功能。在一种语言例如C++中这些应用程序通常借助于多重继承来完成。
4.8.1 接口定义
接口定义很像类定义。下面是一个接口的通用形式:
访问类型 interface 接口名 { //定义抽象类
final 数据类型 成员名称1 = 常量; //数据成员必须赋初值
abstract 返回值的数据类型 方法名称(参数表); //注意抽象方法里没有处理的方式
}
这里,“访问类型”要么是public,要么就没有用修饰符。当没有访问修饰符时,则是默认访问范围,而接口是包中定义的惟一的可以用于其他成员的东西。当它声明为public时,则接口可以被任何代码使用。接口名可以是任何合法的标识符。注意定义的方法没有方法体。它们以参数列表后面的分号作为结束。它们本质上是抽象方法;在接口中指定的方法没有默认的实现。每个包含接口的类必需实现所有的方法。
接口声明中可以声明变量。它们一般是final 和static型的,意思是它们的值不能通过实现类而改变。它们还必须以常量值初始化。如果接口本身定义成public ,所有方法和变量都是public的。
下面列举一实例来说明接口定义的方式。假设定义了一个接口iShape2D,可以利用它来实现二维的几何图形CCircle与CRectangle。对二维的几何形状而言,面积是很重要的计算,因此,可以把计算面积的method声明在接口里,而计算圆面积的pi值是常量,所示可以把他声明在接口的数据成员里。依据这两个概念,我们可以编写出如下的接口。
interface iShape2D //定义接口
{
final double pi=3.14; //数据成员一定要初始化
abstract void area(); //抽象方法,不需要定义处理方式(类体)
}
如前所述,在上面的范例中,Java也许省略了final与abstract关键字,编程如下的程序代码:
interface iShape2D //定义接口
{
double pi=3.14; //数据成员一定要初始化
void area(); //抽象方法,不需要定义处理方式
}
如此一来,每一个接口实现的类必须在类内部定义method的方法,且可自由地使用pi值。
既然接口里只有抽象方法,他只要声明而不用定义处理方式,于是我们自然可以联想到接口也没有办法像一般类一样,用new运算符直接产生对象。相反地,我们必须利用接口的特性来打造一个新的类,在用它来创建对象。利用接口打造新的类的过程,我们称之为接口的实现。
4.8.2 实现接口
一旦接口被定义,一个或多个类可以实现该接口。为实现一个接口,在类定义中包括implements 子句,然后创建接口定义的方法。一个包括implements 子句的类的一般形式如下:
访问类型 class 类名 [extends 超类名] implements 接口名称{
// 类体
}
这里,访问类型要么是public的,要么是没有修饰符的。如果一个类实现多个接口,这些接口被逗号分隔。如果一个类实现两个声明了同样方法的接口,那么相同的方法将被其中任一个接口客户使用。实现接口的方法必须声明成public。而且,实现方法的类型必须严格与接口定义中指定的类型相匹配。
就想你可以想象到的一样,类可以使用接口,只是不用extends,而用implements(实现)
下面是以iShape2D接口来实现CCircle类的范例:
class CCircle implements iShape2D // 实现CCircle类
{
double radius;
public CCircle(double r){
radius=r;
}
public void area(){ // 定义area()的处理方式
System.out.println("area="+pi*radius*radius);
}
}
注意:当实现一个接口方法时,它必须声明成public。
有了上面的理论基础后,我们就可以开始编写程序代码了。exa4_19是以iShape2D接口实现CCircle与Crectangle两个类的范例:
例4-19
// exa4_19, 接口的实现范例
interface iShape2D //定义接口
{
final double pi=3.14;
abstract void area();
}
class CRectangle implements iShape2D // 实现CRectangle类
{
int width,height;
public CRectangle(int w,int h){
width=w;
height=h;
}
public void area(){ // 定义area()的处理方式
System.out.println("area="+width*height);
}
}
class CCircle implements iShape2D // 实现CCircle类
{
double radius;
public CCircle(double r){
radius=r;
}
public void area(){ // 定义area()的处理方式
System.out.println("area="+pi*radius*radius);
}
}
public class exa4_19
{
public static void main(String args[])
{
CRectangle rect=new CRectangle(5,10);
rect.area(); //调用CRectangle类里的area() method
CCircle cir=new CCircle(2.0);
cir.area(); // 调用CCircl类里的area() method
}
}
由本范例的程序代码可以看出,通过接口以及接口的实现在一起的类,我们可以编写出更简洁的程序代码。
前已述及,我们不能直接由接口来创建对象,而必须通过由接口实现的类来创建。虽然如此,我们还是可以声明界面类型的变量(数组),并用它来访问对象。例4_20是利用这个思路写的,其中iShape2D接口、CCircle与Crectangle类的定义均与例4-19相同,故将它们在例4-20中略去,因为在同一目录中,运行不会出现问题。
例4-20
// exa4_20.java, 通过接口类型的变量来访问对象
class exa4_20
{
public static void main(String args[])
{
iShape2D var1,var2; // 声明接口类型的变量
var1=new CRectangle(5,10); // 将接口类型的变量var1指向新建的对象
var1.area(); // 通过接口var1调用area() method
var2=new CCircle(2.0); // 将接口类型的变量var2指向新建的对象
var2.area(); // 通过接口var2调用area() method
}
}
例4-21,用一个类实现多个接口
//exa4_21.java
interface InterfaceExample1
{
int i=4;
void func1();
}
interface InterfaceExample2
{
int k=5;
void func2();
}
class Class3
{
public void func2()
{
System.out.println("func2 in class3");
}
}
public class exa4_21 extends Class3 implements InterfaceExample1,InterfaceExample2
{
int j;
public void func1()
{
System.out.println("func1 in exa4_21");
}
/*
public void func2()
{
System.out.println("func2 in exa4_21");
}
*/
public static void main(String[] args)
{
exa4_21 c=new exa4_21();
c.func1();
c.func2();
}
}
程序中,exa4_21继承了Class3类和两个接口,那么必须把类写在前面,接口写在后面,接口之间用逗号分开,另外注意,由于Class3类实现了func2方法,因此在exa4_21中可以不再实现(当然也可以实现)。
本文详细介绍了Java中的接口,强调接口作为类行为规范的作用。通过接口,定义了类必须实现的方法,但不规定具体实现。接口支持运行时动态方法解析,克服了静态类继承的局限。文中展示了接口定义、实现接口的语法,并给出了多个示例,包括单一接口实现、多个接口实现和接口类型的变量使用。
173万+

被折叠的 条评论
为什么被折叠?



