先上一段代码:
interface Shape {
double area();
static Shape createCircle(double radius) {
return new Circle(radius);
}
static Shape createRectangle(double length, double width) {
return new Rectangle(length, width);
}
}
class Circle implements Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
public void print(){
System.out.println("I'm a circle!");
}
}
class Rectangle implements Shape {
private double length;
private double width;
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
@Override
public double area() {
return length * width;
}
}
public class Main {
public static void main(String[] args) {
Shape circle = Shape.createCircle(5);
System.out.println("Area of Circle: " + circle.area());
circle.print();//程序编译错误
Shape rectangle = Shape.createRectangle(4, 6);
System.out.println("Area of Rectangle: " + rectangle.area());
}
}
接口定义的方法中除了静态工厂方法,其他方法在子类中都要被实现。
Shape circle = Shape.createCircle(5); 尽管**createCircle
方法返回的是Circle
对象,但是由于circle
被声明为Shape
接口类型,所以它只能访问Shape
接口中定义的方法,而不能直接访问Circle
**类中定义的方法。
所以严格来说,**circle
不是Circle
类的实例,而是Shape
接口类型的实例。在Java中,这种情况被称为“多态”,即一个对象可以被看作是其超类或接口类型的实例。这种多态性使得代码更加灵活,能够以通用的方式处理不同的对象。
接口有诸多好处,一为更加直观表示类之间的关联,一为使程序封装性更好,客户端只可以通过接口来沟通ADT,而不能越过接口直接把手伸入ADT。
在Java中,虽然客户端无法直接访问通过接口引用声明的对象的类特定方法,但是可以通过类型转换将接口引用转换为实现类的引用,从而访问实现类的特定方法。这种操作被称为向下转型(Downcasting)这里不展开叙述。