Java 中的多重继承

今天我们将研究Java中的多重继承. 有一段时间,我写了一些关于Java中的 (继承)(/社区/教程/继承-java例), **(界面)(/社区/教程/界面-in-java)**和 **(组成)(/社区/教程/组成-in-java例)**的文章。

Java 中的多重继承

multiple inheritance in java Multiple inheritance in java is the capability of creating a single class with multiple superclasses. Unlike some other popular object oriented programming languages like C++, java doesn't provide support for multiple inheritance in classes. Java doesn't support multiple inheritances in classes because it can lead to diamond problem and rather than providing some complex way to solve it, there are better ways through which we can achieve the same result as multiple inheritances.

Java 中的钻石问题

To understand diamond problem easily, let's assume that multiple inheritances were supported in java. In that case, we could have a class hierarchy like below image. diamond problem in java Let's say SuperClass is an abstract class declaring some method and ClassA, ClassB are concrete classes. SuperClass.java

1package com.journaldev.inheritance;
2
3public abstract class SuperClass {
4
5    public abstract void doSomething();
6}

《Java》

 1package com.journaldev.inheritance;
 2
 3public class ClassA extends SuperClass{
 4    
 5    @Override
 6    public void doSomething(){
 7    	System.out.println("doSomething implementation of A");
 8    }
 9    
10    //ClassA own method
11    public void methodA(){
12    	
13    }
14}

《Java》

 1package com.journaldev.inheritance;
 2
 3public class ClassB extends SuperClass{
 4
 5    @Override
 6    public void doSomething(){
 7    	System.out.println("doSomething implementation of B");
 8    }
 9    
10    //ClassB specific method
11    public void methodB(){
12    	
13    }
14}

现在,让我们假设 ClassC 实现会像下面那样,它正在扩展到 ClassA 和 ClassB。

 1package com.journaldev.inheritance;
 2
 3// this is just an assumption to explain the diamond problem
 4//this code won't compile
 5public class ClassC extends ClassA, ClassB{
 6
 7    public void test(){
 8    	//calling super class method
 9    	doSomething();
10    }
11
12}

请注意,test()方法正在调用doSomething()超级类方法,这导致了模糊性,因为编译器不知道要执行哪个超级类方法。由于钻石形的类图,它被称为Java中的钻石问题。Java中的钻石问题是Java不支持类中的多个继承的主要原因。

Java 接口中的多重继承

你可能已经注意到,我总是说,在类中不支持多个继承,但在接口中得到支持。

1package com.journaldev.inheritance;
2
3public interface InterfaceA {
4
5    public void doSomething();
6}

网址:Java

1package com.journaldev.inheritance;
2
3public interface InterfaceB {
4
5    public void doSomething();
6}

請注意,兩個接口都宣佈相同的方法,現在我們可以有一個擴展這兩個接口的接口如下。

1package com.journaldev.inheritance;
2
3public interface InterfaceC extends InterfaceA, InterfaceB {
4
5    //same method is declared in InterfaceA and InterfaceB both
6    public void doSomething();
7    
8}

这是非常好的,因为接口只是声明方法,实际实现将由具体的类实施接口,所以在Java接口中没有任何类型的模糊性。

 1package com.journaldev.inheritance;
 2
 3public class InterfacesImpl implements InterfaceA, InterfaceB, InterfaceC {
 4
 5    @Override
 6    public void doSomething() {
 7    	System.out.println("doSomething implementation of concrete class");
 8    }
 9
10    public static void main(String[] args) {
11    	InterfaceA objA = new InterfacesImpl();
12    	InterfaceB objB = new InterfacesImpl();
13    	InterfaceC objC = new InterfacesImpl();
14    	
15    	//all the method calls below are going to same concrete implementation
16    	objA.doSomething();
17    	objB.doSomething();
18    	objC.doSomething();
19    }
20
21}

您是否注意到,每次我使用任何超级类方法或实施任何接口方法时,我都会使用 @Override 注释。Override 注释是三种内置 **[java 注释](/社区/教程/java 注释)**中的一个,我们应该使用(/社区/教程/java-override-method-overriding)。

救援的组成

那么如果我们想在ClassC中使用ClassA函数methodA()ClassB函数methodB(),那么该怎么办呢?解决方案在于使用 composition

 1package com.journaldev.inheritance;
 2
 3public class ClassC{
 4
 5    ClassA objA = new ClassA();
 6    ClassB objB = new ClassB();
 7    
 8    public void test(){
 9    	objA.doSomething();
10    }
11    
12    public void methodA(){
13    	objA.methodA();
14    }
15    
16    public void methodB(){
17    	objB.methodB();
18    }
19}

构成 vs 遗产

Java 编程的最佳实践之一是优化构成而不是继承

  1. 联合国 假设我们有一个超级类和子类如下: 'ClassC.java' (- ) ``` (- ) 包 com.journaldev. inheritance; (- ) (- ) 公共类 C{ (- ) 公共无效方法 C{ (- ) (- ) } (- ) ClassD.java (- ) 包 com.journaldev.inheritance; (- ) (- ) 公共类 D 扩展类C{

公用入声测试 (_ 返回 0; } } ___ 上面的代码编译和工作精细,但如果C类的执行像下面这样被改变,怎么办: ClassC.java' package com.journal.dev.inheritance; (- ) (- ) (- ) 公共类 C{ (- ) (- ) (- ) 公共类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 类 现在ClassD不会编译,如果您正在使用任何IDE,它会建议您改变超级类或子类的返回类型. 现在想象一下我们拥有多层次的阶级继承和超阶级不受我们控制的局面. 我们别无选择,只能改变我们的子类方法签名或其名称去除编译错误. 此外,我们必须改变 我们的子阶级方法被引用的所有地方, 因此继承使我们的法典变得脆弱。 上述问题永远不会在组成方面发生,这使得它比继承更为有利。 (_) (英语). 2. 继承的另一个问题是,我们正在将所有超级阶级的方法都暴露给客户,如果我们的超级阶级设计不当,并且存在安全漏洞,那么,尽管我们在执行我们的阶级时要完全小心,但我们却受到超级阶级执行不力的影响. 组成帮助我们提供对超阶级方法的控制,而继承则不能提供对超阶级方法的任何控制,这也是组成相对于继承的主要优势之一. ( (英语). 组成方面的另一个好处是,它为援引方法提供了灵活性。 我们上述 " 分类 " 的实施并不理想,它提供了编译时间,具有将采用的方法的约束性,只要作出最小的改变,我们就可以灵活地采用这种方法,使之具有活力。 ClassC.java' (- )-(- )-(-)-(- )-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-(-)-(-)-(-)-(-(-)-(-)-(-(-)-(-)-(-)-(-)-(-)-(-)-(-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-(-)-(-)-(-(-)-)-(-)-(- 上述方案的产出是:_____________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________ (英语). 4. 单位测试在组成上是容易的,因为我们知道我们从超级阶级那里使用的所有方法,我们可以嘲弄它进行测试,而在继承上,我们严重依赖超级阶级,并且不知道超级阶级的所有方法都会被使用,所以我们需要测试超级阶级的所有方法,这是额外的工作,我们因为继承而需要做不必要的工作. ( (英语)

这是关于Java中的多重继承和简短的构成观点的全部。

Published At
Categories with 技术
Tagged with
comments powered by Disqus