Java接口与多继承

本文深入探讨了Java接口在解决多继承问题中的核心作用及如何巧妙实现类多继承机制。通过实例代码展示了如何使用接口避免钻石危机,以及接口在操作系统与硬件交互、C++多继承与Java接口技术相似目的的应用。同时,介绍了内部类如何在类多继承过程中避免钻石危机。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

摘要 为什么说接口巧妙地实现了类似多继承的机制。使用接口的核心原因是,为了能够向上转型为多个基类型。即利用接口的多实现,可向上转型为多个接口基类型。


  使用接口的核心原因是,为了能够向上转型为多个基类型。即利用接口的多实现,可向上转型为多个接口基类型。以前在学Java的时候对于接口是直接飙过去,并未尝试去深究它的意义,只是简单地记住了它是用来折衷地解决多继承问题。直到最近重新开始复习,才被这一问题弄得晕头转向的。

       先来看一下为何 Java 不支持多继承,原因是多继承容易导致钻石危机(也称棱形问题),用一幅图来说明一下:


  使用接口的核心原因是,为了能够向上转型为多个基类型。即利用接口的多实现,可向上转型为多个接口基类型。以前在学Java的时候对于接口是直接飙过去,并未尝试去深究它的意义,只是简单地记住了它是用来折衷地解决多继承问题。直到最近重新开始复习,才被这一问题弄得晕头转向的。

       先来看一下为何 Java 不支持多继承,原因是多继承容易导致钻石危机(也称棱形问题),用一幅图来说明一下:

       假设 类A 中有一个public方法 fun(),然后 类B 和 类C 同时继承了 类A,在 类B 或 类C 中各自对方法 fun()进行了覆盖,这时 类D 通过多继承同时继承了 类B 和 类C,这样便导致钻石危机了,程序在运行的时候对于方法 fun()该如何判断?

       所以 Java 并不支持多继承,但是 Java 通过接口可以折衷地解决多继承问题,用一段代码来说明一下比较容易理解:



// 接口类HowToEat
public  interface  HowToEat {
     public  abstract  String howToEat();
}


然后编写一个Checken类,暂时把它想象成父类。


public  class  Checken  implements  HowToEat {
     @Override
     public  String howToEat() {
         return  "Chicken: Fry it." ;
     }
}


  再编写一个Orange类,同样暂时把它想象成父类。


public  class  Orange  implements  HowToEat {
     @Override
     public  String howToEat() {
         return  "Orange: Make it juice." ;
     }
}


最后我们通过测试类 MainTest 来理解接口是如何实现类似多继承机制的。


public  class  MainTest {
     public  static  void  main(String[] args) {
         HowToEat test =  new  Checken();
         System.out.println(test.howToEat());
         test =  new  Orange();
         System.out.println(test.howToEat());
     }
}

       上面代码的运行结果如下:





  当我们使用 HowToEat Test = new Checken(); 的时候,接口中的 howToEat() 方法采用 Checken.howToEat() 来实现,当我们使用 test = new Orange() 的时候,接口中的 howToEat() 方法采用 Orange.howToEat() 来实现,这样是不是可以想象成 HowToEat 类同时继承了 Checken 类和 Orange 类,但具体继承哪个特性则在 new 的时候再来进行决定,这样就巧妙地解决钻石危机同时又可以建立类似多继承的机制。

       到这里我们可以进行扩展,接口就是标准。最近在学操作系统,书中讲到“操作系统是用户和计算机硬件之间的接口。用户通过操作系统来使用计算机系统,操作系统则为用户屏蔽了硬件细节,因此,应用程序和用户通常不需要关系计算机的硬件细节”。看到这里,我想大概 C++的多继承和 Java 的接口技术就是想要达到这种目的吧。举个最简单的例子,就是手机和U盘等硬件移动设备都有USB接口,电脑端的USB接口和硬件移动设备的USB接口都遵守一定规则,这样不管你的硬件移动设备内部是怎样实现读写操作的都可以实现与电脑的连接,若不遵守规则则会导致电脑端需要安装成千上万个USB接口。这时我们便可以联想 Java 中的 Comparable等接口了。

       如果对于接口还是无法理解过来,当然也可以使用内部类(嵌套类)来实现类似多继承,不必担心会发生钻石危机,因为用内部类实现多继承过程中由设计者重新进行函数命名,从而避免了钻石危机。下面用代码来进行说明:

       要继承的类 Father。

?
1
2
3
4
5
public  class  Father {
     public  void  output() {
         System.out.println( "father" );
     }
}

       要继承的类 Mother。

?
1
2
3
4
5
public  class  Mother {
     public  void  output() {
         System.out.println( "mother" );
     }
}

       类 Son 同时继承了 Father 和 Mother 的 output() 方法的实现。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public  class  Son {
     class  Father_son  extends  Father {
 
     }
 
     class  Mother_son  extends  Mother {
 
     }
 
     public  void  father() {
         ( new  Father_son()).output();
     }
 
     public  void  mother() {
         ( new  Mother_son()).output();
     }
}

       测试类 MainTest。

?
1
2
3
4
5
6
7
public  class  MainTest {
     public  static  void  main(String[] args) {
         Son test =  new  Son();
         test.father();
         test.mother();
     }
}

       测试结果图如下:

分享到: 


  当我们使用 HowToEat Test = new Checken(); 的时候,接口中的 howToEat() 方法采用 Checken.howToEat() 来实现,当我们使用 test = new Orange() 的时候,接口中的 howToEat() 方法采用 Orange.howToEat() 来实现,这样是不是可以想象成 HowToEat 类同时继承了 Checken 类和 Orange 类,但具体继承哪个特性则在 new 的时候再来进行决定,这样就巧妙地解决钻石危机同时又可以建立类似多继承的机制。

       到这里我们可以进行扩展,接口就是标准。最近在学操作系统,书中讲到“操作系统是用户和计算机硬件之间的接口。用户通过操作系统来使用计算机系统,操作系统则为用户屏蔽了硬件细节,因此,应用程序和用户通常不需要关系计算机的硬件细节”。看到这里,我想大概 C++的多继承和 Java 的接口技术就是想要达到这种目的吧。举个最简单的例子,就是手机和U盘等硬件移动设备都有USB接口,电脑端的USB接口和硬件移动设备的USB接口都遵守一定规则,这样不管你的硬件移动设备内部是怎样实现读写操作的都可以实现与电脑的连接,若不遵守规则则会导致电脑端需要安装成千上万个USB接口。这时我们便可以联想 Java 中的 Comparable等接口了。

       如果对于接口还是无法理解过来,当然也可以使用内部类(嵌套类)来实现类似多继承,不必担心会发生钻石危机,因为用内部类实现多继承过程中由设计者重新进行函数命名,从而避免了钻石危机。下面用代码来进行说明:

       要继承的类 Father。

?
1
2
3
4
5
public  class  Father {
     public  void  output() {
         System.out.println( "father" );
     }
}

       要继承的类 Mother。

?
1
2
3
4
5
public  class  Mother {
     public  void  output() {
         System.out.println( "mother" );
     }
}

       类 Son 同时继承了 Father 和 Mother 的 output() 方法的实现。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public  class  Son {
     class  Father_son  extends  Father {
 
     }
 
     class  Mother_son  extends  Mother {
 
     }
 
     public  void  father() {
         ( new  Father_son()).output();
     }
 
     public  void  mother() {
         ( new  Mother_son()).output();
     }
}

       测试类 MainTest。

?
1
2
3
4
5
6
7
public  class  MainTest {
     public  static  void  main(String[] args) {
         Son test =  new  Son();
         test.father();
         test.mother();
     }
}

       测试结果图如下:

分享到: 


原文:

http://my.oschina.net/keyven/blog/206180

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值