本文共 10203 字,大约阅读时间需要 34 分钟。
多重继承java
Today we will look into Multiple Inheritance in Java. Sometime back I wrote few posts about , and in java. In this post, we will look into java multiple inheritance and then compare composition and inheritance.
今天,我们将研究Java中的多重继承。 有时我写了几篇有关Java , 和的文章。 在本文中,我们将研究Java多重继承,然后比较组成和继承。
Java中的多重继承是创建具有多个超类的单个类的能力。 与其他一些流行的面向对象的编程语言(如C ++)不同, java不提供对类中多重继承的支持 。
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.
为了轻松理解钻石问题, 我们假设java中支持多个继承 。 在这种情况下,我们可以像下面的图像那样有一个类层次结构。
Let’s say SuperClass is an declaring some method and ClassA, ClassB are concrete classes.
假设SuperClass是一个声明了一些方法,而ClassA,ClassB是具体类。
SuperClass.java
SuperClass.java
package com.journaldev.inheritance;public abstract class SuperClass { public abstract void doSomething();}
ClassA.java
ClassA.java
package com.journaldev.inheritance;public class ClassA extends SuperClass{ @Override public void doSomething(){ System.out.println("doSomething implementation of A"); } //ClassA own method public void methodA(){ }}
ClassB.java
ClassB.java
package com.journaldev.inheritance;public class ClassB extends SuperClass{ @Override public void doSomething(){ System.out.println("doSomething implementation of B"); } //ClassB specific method public void methodB(){ }}
Now let’s say ClassC implementation would be something like below and it’s extending both ClassA and ClassB.
现在,让我们说ClassC的实现类似于下面的内容,它扩展了ClassA和ClassB。
ClassC.java
ClassC.java
package com.journaldev.inheritance;// this is just an assumption to explain the diamond problem//this code won't compilepublic class ClassC extends ClassA, ClassB{ public void test(){ //calling super class method doSomething(); }}
Notice that test()
method is making a call to superclass doSomething()
method. This leads to the ambiguity as the compiler doesn’t know which superclass method to execute. Because of the diamond-shaped class diagram, it’s referred to as Diamond Problem in java. The diamond problem in Java is the main reason java doesn’t support multiple inheritances in classes.
注意, test()
方法正在调用超类doSomething()
方法。 由于编译器不知道要执行哪个超类方法,因此这导致了歧义。 由于菱形类图,在Java中被称为Diamond Problem。 Java中的菱形问题是Java不支持类中的多个继承的主要原因。
Notice that the above problem with multiple class inheritance can also come with only three classes where all of them has at least one common method.
请注意,具有多个类继承的上述问题也可能只出现在三个类中,它们全部具有至少一个通用方法。
You might have noticed that I am always saying that multiple inheritances is not supported in classes but it’s supported in interfaces. A single interface can extend multiple interfaces, below is a simple example.
您可能已经注意到,我一直在说类不支持多重继承,但接口则支持多重继承。 单个接口可以扩展多个接口,下面是一个简单的示例。
InterfaceA.java
InterfaceA.java
package com.journaldev.inheritance;public interface InterfaceA { public void doSomething();}
InterfaceB.java
InterfaceB.java
package com.journaldev.inheritance;public interface InterfaceB { public void doSomething();}
Notice that both the interfaces are declaring the same method, now we can have an interface extending both these interfaces like below.
注意,两个接口都声明了相同的方法,现在我们可以拥有一个扩展这两个接口的接口,如下所示。
InterfaceC.java
InterfaceC.java
package com.journaldev.inheritance;public interface InterfaceC extends InterfaceA, InterfaceB { //same method is declared in InterfaceA and InterfaceB both public void doSomething(); }
This is perfectly fine because the interfaces are only declaring the methods and the actual implementation will be done by concrete classes implementing the interfaces. So there is no possibility of any kind of ambiguity in multiple inheritances in Java interfaces.
这很好,因为接口仅声明方法,并且实际实现将由实现接口的具体类完成。 因此,Java接口中的多重继承不存在任何歧义。
That’s why a java class can implement multiple interfaces, something like below example.
这就是为什么Java类可以实现多个接口的原因,例如下面的示例。
InterfacesImpl.java
InterfacesImpl.java
package com.journaldev.inheritance;public class InterfacesImpl implements InterfaceA, InterfaceB, InterfaceC { @Override public void doSomething() { System.out.println("doSomething implementation of concrete class"); } public static void main(String[] args) { InterfaceA objA = new InterfacesImpl(); InterfaceB objB = new InterfacesImpl(); InterfaceC objC = new InterfacesImpl(); //all the method calls below are going to same concrete implementation objA.doSomething(); objB.doSomething(); objC.doSomething(); }}
Did you noticed that every time I am overriding any superclass method or implementing any interface method, I am using @Override annotation. Override annotation is one of the three built-in and we should .
您是否注意到,每次我重写任何超类方法或实现任何接口方法时,我都使用@Override注释。 覆盖注释是三个内置的 , ,我们都应 。
So what to do if we want to utilize ClassA
function methodA()
and ClassB
function methodB()
in ClassC
. The solution lies in using composition. Here is a refactored version of ClassC that is using composition to utilize both classes methods and also using doSomething() method from one of the objects.
那么如果我们想在ClassC
利用ClassA
函数methodA()
和ClassB
函数methodB()
ClassC
。 解决方案在于使用组合 。 这是ClassC的重构版本,它使用合成来利用两个类方法以及一个对象中的doSomething()方法。
ClassC.java
ClassC.java
package com.journaldev.inheritance;public class ClassC{ ClassA objA = new ClassA(); ClassB objB = new ClassB(); public void test(){ objA.doSomething(); } public void methodA(){ objA.methodA(); } public void methodB(){ objB.methodB(); }}
One of the best practices of Java programming is to “favor composition over inheritance”. We will look into some of the aspects favoring this approach.
Java编程的最佳实践之一是“偏向于继承而不是继承”。 我们将研究有利于这种方法的某些方面。
ClassC.java
package com.journaldev.inheritance;public class ClassC{ public void methodC(){ }}
ClassD.java
The above code compiles and works fine but what if ClassC implementation is changed like below:
ClassC.java
package com.journaldev.inheritance;public class ClassC{ public void methodC(){ } public void test(){ }}
Notice that test()
method already exists in the subclass but the return type is different. Now the ClassD won’t compile and if you are using any IDE, it will suggest you change the return type in either superclass or subclass.
Now imagine the situation where we have multiple levels of class inheritance and superclass is not controlled by us. We will have no choice but to change our subclass method signature or its name to remove the compilation error. Also, we will have to make a change in all the places where our subclass method was getting invoked, so inheritance makes our code fragile.
The above problem will never occur with composition and that makes it more favorable over inheritance.
ClassC.java
ClassD.java
package com.journaldev.inheritance;public class ClassD extends ClassC{ public int test(){ return 0; }}
上面的代码可以编译并正常工作,但是如果ClassC实现更改如下:
ClassC.java
请注意,子类中已经存在test()
方法,但返回类型不同。 现在,ClassD将无法编译,并且如果您使用的是任何IDE,它将建议您更改超类或子类中的返回类型。
现在想象一下我们具有多个级别的类继承和超类不受我们控制的情况。 我们别无选择,只能更改子类方法签名或其名称以消除编译错误。 同样,我们将必须在所有调用子类方法的地方进行更改,因此继承会使我们的代码易碎。
上面的问题永远不会在组合中发生,这使其比继承更有利。
Composition helps us in providing controlled access to the superclass methods whereas inheritance doesn’t provide any control of the superclass methods, this is also one of the major advantages of composition over inheritance.
组合可以帮助我们提供对超类方法的受控访问,而继承不提供对超类方法的任何控制,这也是组合优于继承的主要优势之一。
ClassC
is not optimal and provides compile-time binding with the method that will be invoked, with minimal change we can make the method invocation flexible and make it dynamic.ClassC.java
package com.journaldev.inheritance;public class ClassC{ SuperClass obj = null; public ClassC(SuperClass o){ this.obj = o; } public void test(){ obj.doSomething(); } public static void main(String args[]){ ClassC obj1 = new ClassC(new ClassA()); ClassC obj2 = new ClassC(new ClassB()); obj1.test(); obj2.test(); }}
Output of above program is:
This flexibility in method invocation is not available in inheritance and boosts the best practice to favor composition over inheritance.
ClassC
实现不是最佳的,它提供了与将要调用的方法的编译时绑定,只需进行很小的更改,我们就可以灵活地使方法调用并使之动态。 ClassC.java
package com.journaldev.inheritance;public class ClassC{ SuperClass obj = null; public ClassC(SuperClass o){ this.obj = o; } public void test(){ obj.doSomething(); } public static void main(String args[]){ ClassC obj1 = new ClassC(new ClassA()); ClassC obj2 = new ClassC(new ClassB()); obj1.test(); obj2.test(); }}
上面程序的输出是:
这种方法调用的灵活性在继承中不可用,并提倡了最佳实践,即在继承方面偏向于组合。
That’s all for multiple inheritances in java and a brief look at composition.
这就是java中的多个继承以及对组合的简要介绍。
翻译自:
多重继承java
转载地址:http://yklzd.baihongyu.com/