首页 > 代码库 > 组合接口时名字冲突问题

组合接口时名字冲突问题

  之前从没注意到实现多个接口可能会存在方法冲突的问题,在《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()。

 总结:

  • 类不可以多重继承,接口可以多重继承;
  • 组合接口时,可能会存在方法重载和重写的问题,并且可能会引入代码的混乱,降低代码可读性,故尽量避免这种情况;
  • 通过该例,可以学习继承、接口实现、重载和重写概念,其中一点是类继承的方法也可以作为实现接口的实现方法。

 

组合接口时名字冲突问题