很多时候 ,我们实际上关心的,不是对象的类型,而是对象的能力。
比如要将冷水加热,只要得到热水即可。至于是用电磁炉还是燃气灶还是电热壶加热,并不重要。重要的是对象是否有加热水的能力。
Java使用接口这个概念来表示能力。
接口声明了一组能力,但它自己并没有实现这个能力,它只是一个约定。
它涉及交互两方对象,一方需要实现这个接口,另一方使用这个接口,但双方对象并不直接互相依赖,它们只是通过接口间接交互。
通过接口间接交互
定义接口
首先定义一个用来比较的接口,叫MyComparable。
1 2 3
| public interface MyComparable { int compareTo(Object other); }
|
interface关键字声明接口,修饰符一般都是public。
MyComparable接口定义里,声明了一个方法compareTo,但没有定义方法体,接口都不实现方法。接口方法不需要加修饰符,加与不加都是public的,不能是别的修饰符。
接口与类不同,它的方法没有实现代码。接口还需要至少两个参与者,一个需要实现接口,另一个使用接口。
实现接口
类可以实现接口,表示类的对象具有接口所表示的能力。
假设让Point类计算出到原点的距离,再将距离进行比较。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| public class Point implements MyComparable{ private int x; private int y;
public Point(int x, int y) { this.x = x; this.y = y; }
public double distance(){ return Math.sqrt(x*x+y*y); }
public int getX() { return x; }
public int getY() { return y; }
@Override public String toString() { return "("+x+","+y+")"; }
@Override public int compareTo(Object other) { if (!(other instanceof Point)) { throw new IllegalArgumentException(); } Point otherPoint = (Point)other; double delta = distance() - otherPoint.distance(); if(delta < 0) { return -1; }else if (delta > 0) { return 1; }else { return 0; } } }
|
java使用implements关键字表示实现接口,前面是类名,后面是接口名。
java的普通类实现接口,必须要实现接口中声明的每一个方法。
一个类可以实现多个接口,表明类的对象具备多种能力,各个接口之间以逗号分隔,语法如下:
1 2 3
| public class Test implements Interface1, Interface2 { ... }
|
使用接口
与类不同,接口不能new,不能直接创建一个接口对象,对象只能通过类来创建。但可以声明接口类型的变量,引用实现了接口的类对象。
例如:
1 2 3 4
| MyComparable p1 = new Point(2,3); MyComparable p2 = new Point(1,2); System.out.println(p1.compareTo(p2));
|
p1和p2是MyComparable类型的变量,但引用了Point类型的对象,之所以能赋值是因为Point实现了MyComparable接口。
如果一个类型实现了多个接口,那这种类型的对象就可以被赋值给任一接口类型的变量。
p1和p2能且只能调用MyComparable接口的方法。实际执行时,执行的是具体实现类的代码。