你可以把变量定义成使用接口的对象引用而不是类的类型。任何实现了所声明接口的类的实例都可以被这样的一个变量引用。当你通过这些引用调用方法时,在实际引用接口的实例的基础上,方法被正确调用。这是接口的最显著特性之一。
被执行的方法在运行时动态操作,允许在调用方法代码后创建类。调用代码在完全不知“调用者”的情况下可以通过接口来调度。
警告:因为Java中在运行时动态查询方法与通常的方法调用相比会有一个非常庞大的花费,所以在对性能要求高的代码中不应该随意的使用接口。
下面的例子通过接口引用变量调用callback( )方法:
class TestIface {
public static void main(String args[]) {
Callback c = new Client();
c.callback(42);
}
}
该程序的输出如下:
callback called with 42
注意变量c被定义成接口类型Callback,而且被一个Client实例赋值。尽管c可以用来访问Callback()方法,它不能访问Client类中的任何其他成员。一个接口引用变量仅仅知道被它的接口定义声明的方法。因此,c不能用来访问nonIfaceMeth( ),因为它是被Client定义的,而不是由Callback定义。
前面的例子机械的显示了一个接口引用变量怎样访问一个实现对象,它没有说明这样的引用的多态功能。为演示这个用途,首先创建Callback的第二个实现,如下:
// Another implementation of Callback.
class AnotherClient implements Callback {
// Implement Callback's interface
public void callback(int p) {
System.out.println("Another version of callback");
System.out.println("p squared is " + (p*p));
}
}
现在,试试下面的类:
class TestIface2 {
public static void main(String args[]) {
Callback c = new Client();
AnotherClient ob = new AnotherClient();
c.callback(42);
c = ob; // c now refers to AnotherClient object
c.callback(42);
}
}
程序输出如下:
callback called with 42
Another version of callback
p squared is 1764
如你所见,被调用的callback( )的形式由在运行时c引用的对象类型决定。这是一个非常简单的例子,下面你将会看到另一个例子,它更实用。
局部实现
如果一个类包含一个接口但是不完全实现接口定义的方法,那么该类必须定义成abstract型。例如:
abstract class Incomplete implements Callback {
int a, b;
void show() {
System.out.println(a + " " + b);
}
// ...
}
这里,类Incomplete没有实现callback( )方法,必须定义成抽象类。任何继承Incomplete的类都必须实现callback( )方法或者它自己定义成abstract类。