何谓接口
接口定义行为
在Java中使用interface关键字来定义接口:
public interface Swimmer{
public abstract void swim();
}
接口可以用于定义行为但不定义操作,在这里Swimmer中的swim()方法没有操作,直接标示为abstract,而且一定是public。对象若想拥有Swimmer定义的行为,就必须操作Swimmer接口。
例如,Fish拥有Swimmer行为:
public abstract class Fish implements Swimmer {
protected String name;
public Fish(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public abstract void swim();
}
以Java的语意来说,继承会有“是一种”关系,操作接口则表示“拥有行为”。
行为的多态
会使用接口定义行为之后,也要再来当编译程序,看看哪些是合法的多态语法。判断方式是“右边是不是拥有左边的行为”,或者是“右边对象是不是操作了左边接口”。
Swimmer swimmer = new Shark();
Shark shark = swimmer;
第一行:Shark拥有Swimmer的行为,编译成功
第二行:有Swimmer行为的对象不一定是Shark,编译失败
Swimmer swimmer = new Shark();
Shark shark = (Shark)swimmer;
第一行:编译成功
第二行:让有Swimmer行为的对象“扮演”Shark,编译成功
Swimmer swimmer = new Human();
Shark shark = (Shark)swimmer;
第一行:编译成功
第二行:swimmer实际上参考了Human实例,所以不能扮演Shark,编译失败
解决需求变化
在Java中,类可以操作两个以上的类,也就是拥有两种以上的行为,类也可以同时继承某个类,并操作某些接口。
接口语法细节
接口的默认
在Java中,可使用interface来定义抽象的行为与外观,如接口中的方法可声明为public abstract。接口中的方法没有操作时,一定得是公开且抽象,为了方便也可以省略public abstract,编译程序会自动加上。
public interface Swimmer{
void swim();
}
有一个这样的题目:
interface Action {
void excute();
}
class Some implements Action {
void excute() {
System.out.println("做一些服务");
}
}
public class Main() {
public static void main(String[] args) {
Action action = new Some();
action.excute();
}
}
“请问执行的结果?”这个问题是个陷阱,编译失败。
因为Action中定义的excute()其实默认为public abstract,而Some类在操作excute()方法时,没有撰写public,因此默认位包权限,这等于是将Action中public的方法缩小为包权限,所以编译失败。必须将Some类的excute()设为public才可以通过编译。
在interface中可以定义常数:
public interface Action {
public static final int STOP = 0;
public static final int RIGHT = 1;
public static final int LEFT = 2;
public static final int UP = 3;
public static final int DOWN = 4;
Java中经常见到在接口中定义这些常数,称为枚举常数,为了方便,也可以省略public static final,所以也可以这样写:
public interface Action {
int STOP = 0;
int RIGHT = 1;
int LEFT = 2;
int UP = 3;
int DOWN = 4;
}
在类中也可以定义枚举常数,不过要明确写出public static final。
接口可以继承别的接口,也可以同时继承两个以上的接口。
如果父接口中定义的方法有操作,也代表了继承父接口的操作。
使用enum枚举常数
public enum Action {
STOP,RIGHT,LEFT,DOWN
}
实际上,enum定义了特殊的类,继承自java.lang.Enum,不过这是由编译程序处理,直接撰写程序继承Enum类会被编译程序拒绝。