首页 > 代码库 > 组合接口时名字冲突问题
组合接口时名字冲突问题
之前从没注意到实现多个接口可能会存在方法冲突的问题,在《Thinking in Java》中看到一个有趣的例子,其本质是重载和重写的问题,关于重载和重写的概念和区别可参看另一篇文章Java基础一:面向对象的特征。首先看例子:
1 interface I1 { 2 void f(); 3 } 4 5 interface I2 { 6 int f(int i); 7 } 8 9 interface I3 {10 int f();11 }12 13 class C {14 public int f(){15 return 1;16 }17 }18 19 class C2 implements I1,I2{//重载20 @Override21 public void f() {}22 23 @Override24 public int f(int i) {25 return 0;26 }27 }28 29 class C3 extends C implements I2{30 @Override31 public int f(int i) {//重载32 return 0;33 }34 }35 36 class C4 extends C implements I3{37 @Override38 public int f() { //重写39 return 0;40 }41 }42 43 // class C5 extends C implements I1{}44 //45 // interface I4 extends I1,I3{}46 47 public static void main(String[] args){48 MethodCollision methodCollision = new MethodCollision();49 C4 c4 = methodCollision.new C4();50 System.out.println(c4.f());//输出051 }
其中接口I1中存在方法void f(),I2中存在int f(int i),I3中存在int f(),类C中存在int f()的方法。
C2类实现接口I1和I2,其中实现的方法void f()和int f(int i)具有不同的签名,属于重载;
C3类实现接口I2、继承C,C3实现I2中的int f(int i),并继承C中的int f()方法,它们具有不同的签名,属于重载;
C4类实现接口I3、继承C,C4实现I3中的int f(),并继承C中的int f()方法,它们具有相同的签名,并且返回值类型也相同,属于重写(从程序输出0可以说明);
C5类实现接口I1、继承C,理论上,C5类会分别实现和继承I1方法void f()和C方法int f(),它们具有相同的签名,不同的返回值类型,既不是重写,也不能重载,故编译器提示错误;
I4接口继承I1和I3,同样理论上继承void f()和int f(),但既不是重写,也无法重载,编译器报错。
另一个有趣问题是,我如果将接口I1中的void f()改为int f(),会产生什么效果呢?
1 interface I1 { 2 int f(); 3 } 4 5 interface I2 { 6 int f(int i); 7 } 8 9 interface I3 {10 int f();11 }12 13 class C {14 public int f(){15 return 1;16 }17 }18 19 class C2 implements I1,I2{//重载20 @Override21 public int f() {22 return 0;23 }24 25 @Override26 public int f(int i) {27 return 0;28 }29 }30 31 class C3 extends C implements I2{32 @Override33 public int f(int i) {//重载34 return 0;35 }36 }37 38 class C4 extends C implements I3{39 @Override40 public int f() { //重写41 return 0;42 }43 }44 45 class C5 extends C implements I1{}//不重写该函数,继承自C的方法即为实现46 47 interface I4 extends I1,I3{}48 49 class C6 implements I4{//I1和I3的方法一样,实现类只实现一个50 @Override51 public int f() {52 return 0;53 }54 }55 56 public static void main(String[] args){57 MethodCollision methodCollision = new MethodCollision();58 C4 c4 = methodCollision.new C4();59 System.out.println(c4.f());//060 61 C5 c5 = methodCollision.new C5();62 System.out.println(c5.f());//163 }
其中接口I1中存在方法int f(),I2中存在int f(int i),I3中存在int f(),类C中存在int f()的方法。
C2类实现接口I1和I2,其中实现的方法int f()和int f(int i)具有不同的签名,属于重载;
C3类实现接口I2、继承C,属于重载;
C4类实现接口I3、继承C,属于重写(从程序输出0可以说明);
C5类实现接口I1、继承C,C5类会分别实现和继承I1方法int f()和C方法int f(),其与C4类是相同的,它是重写吗?不是,因为其继承自C的函数已经实现了该接口,没有重写(从程序输出1可以说明);
I4接口继承I1和I3,同时继承I1和I3的int f(),它们具有相同的方法签名和返回值类型,所以I4具有一个int f()(可通过C6实现类看出);
C6类实现接口I4,具有一个实现函数int f()。
总结:
- 类不可以多重继承,接口可以多重继承;
- 组合接口时,可能会存在方法重载和重写的问题,并且可能会引入代码的混乱,降低代码可读性,故尽量避免这种情况;
- 通过该例,可以学习继承、接口实现、重载和重写概念,其中一点是类继承的方法也可以作为实现接口的实现方法。
组合接口时名字冲突问题