组合接口时名字冲突问题

  之前从没注意到实现多个接口可能会存在方法冲突的问题,在《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         @Override
21         public void f() {}
22 
23         @Override
24         public int f(int i) {
25             return 0;
26         }
27     }
28 
29     class C3 extends C implements I2{
30         @Override
31         public int f(int i) {//重载
32             return 0;
33         }
34     }
35 
36     class C4 extends C implements I3{
37         @Override
38         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());//输出0
51     }

   其中接口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         @Override
21         public int f() {
22             return 0;
23         }
24 
25         @Override
26         public int f(int i) {
27             return 0;
28         }
29     }
30 
31     class C3 extends C implements I2{
32         @Override
33         public int f(int i) {//重载
34             return 0;
35         }
36     }
37 
38     class C4 extends C implements I3{
39         @Override
40         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         @Override
51         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());//0
60 
61         C5 c5 = methodCollision.new C5();
62         System.out.println(c5.f());//1
63     }

   其中接口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()。

 总结:

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