Java中的接口
六. 接口
特性1 - 解决单继承
语法如下
interface A {public default void a() {}
}interface B {public default void b() {}
}// C 从 A, B 两个接口重用方法 a() 和 b()
class C implements A, B {}
解决之前的问题
public class TestInterface1 {public static void main(String[] args) {Duck d = new Duck();d.swim();d.fly();}
}interface Swimmable {default void swim() {System.out.println("游泳");}
}interface Flyable {default void fly() {System.out.println("飞翔");}
}class Duck implements Swimmable, Flyable {}
- 需要放入接口的方法, 必须加 default 关键字(默认方法)
- default 方法只能是 public, public 可以省略
特性2 - 接口多态
- 用父类型代表子类对象,或者用接口类型来代表实现类对象
- 必须发生方法重写
看这张图,上面这是接口E,下面这俩类 F、G 实现了接口,他俩以后可以叫做实现类,看一下这种上下级关系就可以知道,它们之间符合向上转型,F,G能够沿箭头向上转换为接口类型,因此能用接口类型代表实现类对象
先来看第一条,接口类型可以代表实现类对象
public class TestInterface2 {public static void main(String[] args) {E[] array = new E[] {new F(),new G()};}
}
interface E {
}
class F implements E {
}
class G implements E {
}
再看第二条,方法重写
public class TestInterface2 {public static void main(String[] args) {E[] array = new E[] {new F(),new G()};for (int i = 0; i < array.length; i++) {E e = array[i];e.e(); // 多态}}
}
interface E {default void e() { System.out.println("e");}
}
class F implements E {@Overridepublic void e() { System.out.println("f");}
}
class G implements E {@Overridepublic void e() {System.out.println("g");}
}
- 要注意:方法重写时,要求:子类和实现类 方法访问修饰符 >= 父类和接口 方法访问修饰符
- default 方法的访问修饰符其实是省略了 public,实现类中方法的访问修饰符要 >= public 才不会出错
- 多态性:
- 表面调用的是接口的 E.e() 方法
- 实际会根据 e 的实际类型调用重写方法,即 F.e() 和 G.e() 方法
抽象方法
其实要使用接口多态,更多地是使用一种抽象方法,而非默认方法,所谓抽象方法仅有方法声明,没有方法体代码。
它包含 abstract 关键字,而且也只能是 public 的,平时这俩关键字都可以省略不写
public class TestInterface2 {public static void main(String[] args) {E[] array = new E[] {new F(),new G()};for (int i = 0; i < array.length; i++) {E e = array[i];e.e(); // 多态}}
}
interface E {void e(); // 抽象方法,没有方法体,只能是 public 的,省略了 public abstract
}
class F implements E {@Overridepublic void e() { // 默认System.out.println("f");}
}
class G implements E {@Overridepublic void e() {System.out.println("g");}
}
为啥抽象方法设计为不需要方法体呢?因为你看:
- 反正多态要求实现类发生方法重写,既然方法重写了,就调用不到接口方法的代码了
- 既然多态发生时,用不到接口中可能的代码,还不如让方法体空着
另外,抽象方法有个好处:它强制了实现类要实施方法重写,如果实现类没有重写,语法上会报错
特性3 - 接口封装
接口封装的更为彻底
public class TestInterface3 {public static void main(String[] args) {M m = new N(); // 用接口类型代表了实现类对象m.m(); // 只能调用接口中定义的方法}
}interface M {void m(); // public abstract
}class N implements M {public String name;@Overridepublic void m() {System.out.println("m");}public void n() {System.out.println("n");}
}
- 只能调用到接口中的方法,对实现类中的其它方法,一无所知
- 接口限制了只能通过方法来使用对象,不能直接访问对象的字段
封装的关键在于,对外隐藏实现细节,接口完美地做到了这一点
经验
- 在声明方法的参数、返回值,定义变量时,能用接口类型,就用接口类型,有更好的扩展性