前面说过一个类要使用一个接口就要实现该接口中的全部方法,但是很明显Hero没有显式实现CanFight中的fight()方法。仔细观察可以发现,Hero继承的具体类ActionCharacter中有实现了的fight()方法。这样,Hero也相当于实现了fight()方法。需要注意,继承的具体类要写在前面。
使用接口的核心原因上面的例子展示了使用接口的核心原因:
为了能够向上转型为多个基类型;
第二个原因则是与抽象基类相同:防止客户端程序员创建该类的对象,并确保这仅仅是一个接口。
使用继承来扩展接口我们可以通过继承一个接口并添加新的方法声明以生成新的接口,或者通过继承多个接口以实现新的接口。这两种方法都是扩展接口的主要方法。
interface Monster{ void menace(); } //继承并添加新的方法以生成新的接口 interface DangerousMonster extends Monster{ void destroy(); } //继承多个接口,组合成一个新接口 interface Lethal{ void kill(); } interface Vampire extends DangerousMonster, Lethal{ void drinkBlood(); } 组合接口时的名字冲突在前面多重继承中,遇到CanFight和ActionCharacter都有一个相同的方法void fight(),但是这并没有导致什么问题。
但是,如果在组合多个接口时出现两个签名不一样或者返回类型不同的方法时,会不会出现问题呢?
interface I1{ void f(); } interface I2{ int f(int i);} interface I3{ int f();} class C { public int f(){ return 1;}} class C2 implements I1, I2{ //两个方法重载 public void f(){} public int f(int i){ return i;} } class C3 extends C implements I2{ public int f(int i){ return i;} //重载 } class C4 extends C implements I3{ //同CanFight和ActionCharacter一样 } //以下两种方式不行!!! //class C5 extends C implements I1{} //interface I4 extends I1, I3{}重载仅依靠返回类型是无法区分的。在打算组合不同接口中使用相同的方法名通常会造成代码可读性的混乱,这是需要避免的。
接口与工厂接口是实现多重继承的途径,而生成遵循某个接口的对象的典型方式就是工厂方法设计模式。与直接调用构造器不同,在工厂对象上调用的是创建方法,为该工厂对象将直接生成接口的某个实现的对象。理论上,通过这种方式,代码将完全与接口的实现分离,这就使得我们可以透明地将某个实现替换为另一个实现。使用工厂模式的一个常见原因便是创建框架。
interface Service{ void method1(); void method2(); } interface ServiceFactory{ Service getService(); } class Implementation1 implements Service{ Implementation1(){} public void method1(){System.out.println("Implementation1 method1");} public void method2(){System.out.println("Implementation1 method1");} } class Implementation1Factory implements ServiceFactory{ public Service getService(){ return new Implementation1(); } } class Implementation2 implements Service{ Implementation2(){} public void method1(){System.out.println("Implementation2 method1");} public void method2(){System.out.println("Implementation2 method1");} } class Implementation2Factory implements ServiceFactory{ public Service getService(){ return new Implementation2(); } } public class Factories{ public static void serviceConsumer(ServiceFactory fact){ Service s = fact.getService(); s.method1(); s.method2(); } public static void main(String args[]){ serviceConsumer(new Implementation1Factory()); serviceConsumer(new Implementation2Factory()); } } /* output: Implementation1 method1 Implementation1 method1 Implementation2 method1 Implementation2 method1 */ 小结Java中接口的最大意义就在于对外接口与实现分离,一个接口可以有不同的实现,减少了代码中的耦合性。在本篇博文中还提到了三种设计模式:策略模式、适配器模式以及工厂模式,对三种设计模式介绍地比较简单。在看《Java编程思想》时,也是首次学习,会存在不少疏忽之处,望各位看官指出。最后,在Java 8中,接口是有新的特性的,可以拥有方法实体,但是要声明为default。对接口的介绍暂时到此,以后再继续深入介绍。
参考:
[1] Eckel B. Java编程思想(第四版)[M]. 北京: 机械工业出版社, 2007