多重继承java_Java中的多重继承与组合vs继承

多重继承java

有时我写了几篇有关Java 继承接口组成的文章。 在这篇文章中,我们将研究多重继承,然后了解组成优于继承的好处。

Java中的多重继承

多重继承是创建具有多个超类的单个类的能力。 与其他一些流行的面向对象的编程语言(如C ++)不同, java不提供对类中多重继承的支持 。 Java不支持类中的多重继承,因为它可能导致菱形问题 ,而不是提供一些复杂的方法来解决它,而是有更好的方法来实现与多重继承相同的结果。

钻石问题

为了轻松理解钻石问题,我们假设Java中支持多重继承。 在这种情况下,我们可以像下面的图像那样有一个类层次结构。

钻石问题多重继承

假设SuperClass是一个抽象类,声明了一些方法,而ClassA,ClassB是具体类。

超类.java

package com.journaldev.inheritance;public abstract class SuperClass {public abstract void doSomething();
}

ClassA.java

package com.journaldev.inheritance;public class ClassA extends SuperClass{@Overridepublic void doSomething(){System.out.println("doSomething implementation of A");}//ClassA own methodpublic void methodA(){}
}

ClassB.java

package com.journaldev.inheritance;public class ClassB extends SuperClass{@Overridepublic void doSomething(){System.out.println("doSomething implementation of B");}//ClassB specific methodpublic void methodB(){}
}

现在,让我们说ClassC的实现类似于以下内容,它扩展了ClassA和ClassB。

ClassC.java

package com.journaldev.inheritance;public class ClassC extends ClassA, ClassB{public void test(){//calling super class methoddoSomething();}}

注意, test()方法正在调用超类doSomething()方法,这导致歧义,因为编译器不知道要执行哪个超类方法,并且由于菱形类图,它被称为Diamond Problem,这是Java不支持类中的多重继承的主要原因。

请注意,具有多个类继承的上述问题也可能只出现在三个类中,它们全部具有至少一个通用方法。

接口中的多重继承

您可能已经注意到,我一直在说类不支持多重继承,但接口支持多重继承,并且单个接口可以扩展多个接口,下面是一个简单的示例。

接口A.java

package com.journaldev.inheritance;public interface InterfaceA {public void doSomething();
}

接口B.java

package com.journaldev.inheritance;public interface InterfaceB {public void doSomething();
}

注意,两个接口都声明了相同的方法,现在我们可以拥有一个扩展这两个接口的接口,如下所示。

接口C.java

package com.journaldev.inheritance;public interface InterfaceC extends InterfaceA, InterfaceB {//same method is declared in InterfaceA and InterfaceB bothpublic void doSomething();}

这样做非常好,因为接口仅声明方法,并且实际实现将由实现接口的具体类来完成,因此在接口的多重继承中不存在任何歧义的可能性。

这就是为什么Java类可以实现多重继承的原因,例如下面的示例。

接口Impl.java

package com.journaldev.inheritance;public class InterfacesImpl implements InterfaceA, InterfaceB, InterfaceC {@Overridepublic 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 implementationobjA.doSomething();objB.doSomething();objC.doSomething();}}

您是否注意到,每当我覆盖任何超类方法或实现任何接口方法时,我都使用@Override注释,它是三个内置的Java注释之一,并且在覆盖任何方法时都应始终使用覆盖注释 。

救援人员组成

因此,如果我们想在ClassC使用ClassA函数methodA()ClassB函数methodB() ,该解决方案在于使用composition ,这是ClassC的重构版本,该版本使用了composition来利用这两种类方法以及doSomething ()方法来自其中一个对象。

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();}
}

组合与继承

Java编程的最佳实践之一是“通过接口支持组合”,我们将研究一些偏爱这种方法的方面。

  1. 假设我们有一个超类和子类,如下所示:

    ClassC.java

    package com.journaldev.inheritance;public class ClassC{public void methodC(){}
    }

    ClassD.java

    package com.journaldev.inheritance;public class ClassD extends ClassC{public int test(){return 0;}
    }

    上面的代码可以编译并正常工作,但是如果ClassC实现更改如下:

    ClassC.java

    package com.journaldev.inheritance;public class ClassC{public void methodC(){}public void test(){}
    }

    请注意,子类中已经存在test()方法,但返回类型有所不同,现在ClassD将无法编译,并且如果您使用的是任何IDE,它将建议您更改超类或子类中的返回类型。

    现在想象一下这样的情况:我们具有多个级别的类继承,并且超类不受我们控制,我们别无选择,只能更改子类方法签名或名称以消除编译错误,我们还必须在所有方面进行更改子类方法被调用的地方,因此继承使我们的代码易碎。

    上面的问题永远不会在组合中发生,这使其比继承更有利。

  2. 继承的另一个问题是,我们将所有超类方法公开给客户端,并且如果我们的超类设计不当且存在安全漏洞,那么即使我们在实现类时全神贯注,我们也会受到不佳实现的影响。超类。
    组合可以帮助我们提供对超类方法的受控访问,而继承不提供对超类方法的任何控制,这也是组合优于继承的主要优势之一。
  3. 组合的另一个好处是它提供了方法调用的灵活性。 我们上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();}
    }

    上面程序的输出是:

    doSomething implementation of A
    doSomething implementation of B

    这种方法调用的灵活性在继承中不可用,并提倡了最佳实践,即在继承方面偏向于组合。

  4. 单元测试很容易组合,因为我们知道超类中正在使用的所有方法,并且可以对其进行模拟,而在继承中,我们很大程度上依赖于超类,并且不知道将使用所有超类方法,因此我们需要要测试超类的所有方法,这是一项额外的工作,由于继承,我们不需要这样做。

理想情况下,仅当在所有情况下父类和子类的“ is-a ”关系均成立时才应使用继承,否则我们应该继续进行组合。

参考: Developer Recipes博客上的JCG合作伙伴 Pankaj Kumar的Java多重继承与Composition vs Inheritance 。

翻译自: https://www.javacodegeeks.com/2013/08/multiple-inheritance-in-java-and-composition-vs-inheritance.html

多重继承java

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/347330.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数电实验二-点亮一个数码管(Multisim和Basys3 )

特别说明:该系列内容均是本人实验记录,无盗取侵权之嫌,仅供参考,请多动手实践。 一、实验目的 详见报告 二、实验环境 详见报告 三、实验内容 (1)基本要求:以Basys3四位拨码开关SW3~SW0为输入…

模拟调频信号FM解调的matlab和C语言实现【姊妹篇1基于std::vector】

本文所需的FM已调信号、原始音频、包络检波法解调后的音频、差分相位法解调后的音频,可通过以下链接进行下载。其中,FM已调信号文件较大共有两百多兆,故截取其部分上传,若有需要完整信号的请留言! FM调制解调音频文件.rar 已调信号:采样率为 F s = 5 m H z Fs=5mHz Fs=

倍福(Beckhoff)嵌入式控制器PLC

前些天发现了十分不错的人工智能学习网站,通俗易懂,风趣幽默,没有广告,分享给大家,大家可以自行看看。(点击跳转人工智能学习资料) 摘要:与家喻户晓的西门子相比,倍福&am…

fftw-3.3.8库在linux下的的编译和配置

关注公号【逆向通信猿】更精彩!!! 运行环境 Ubuntu 14.04版本以上,64位系统 FFTW库的下载 首先在官网上下载fftw-3.3.8.tar.gz压缩包,解压。本人下载好的压缩包地址:https://download.csdn.net/download/wlwdecs_dn/12904577 FFTW库的生成 首先,将压缩包进行解压,…

tms tck_两个用于Eclipse的TCK –开源到底有什么?

tms tck早在5月,Oracle就向Eclipse Foundation 授予了兼容性测试奖学金 。 在过去的几天里,这引起了媒体的关注,我只是想确保我对整个过程和详细动作有所了解。 看起来像是一见钟情的简单诚实的礼物实际上具有更多的方面。 但是让我们从头开始…

倍福嵌入式控制器PLC各型号简介

CX8000 性能强大的 32 位控制器,集成现场总线和 I/O 接口 CX8000 系列产品是一款可编程控制器,搭载 32 位 ARM 处理器,可用于处理 PLC 程序或用作为上位现场总线系统的从站设备。与 EK 系列总线耦合器(EtherCAT 耦合器&#xff0…

循环自相关函数和谱相关密度(一)——公式推导

1 引言 R ^ x α ( f ) ≡ 0 \hat R_x^\alpha (f) \equiv 0 R<

Spring Security with Spring Boot 2.0:密码编码器

在上一篇文章中&#xff0c;我们使用了用户详细信息服务&#xff0c;以便提供一种基于给定用户名从函数加载数据的方法。 用户详细信息的实现可能由内存机制&#xff0c;sql / no-sql数据库等支持。 选项是无限的。 关于密码存储&#xff0c;我们必须注意的是密码哈希。 出…

第十二届蓝桥杯省赛:试题 A: 卡片(Java)

本题总分&#xff1a;5 分 【问题描述】 小蓝有很多数字卡片&#xff0c;每张卡片上都是数字0到9。 小蓝准备用这些卡片来拼一些数&#xff0c;他想从1开始拼出正整数&#xff0c;每拼一个&#xff0c;就保存起来&#xff0c;卡片就不能用来拼其它数了。 小蓝想知道自己能从1拼…

循环自相关函数和谱相关密度(二)——实信号、复信号模型下的BPSK信号循环谱推导

说明&#xff1a;接上一节循环自相关函数和谱相关密度&#xff08;一&#xff09;——公式推导 7 BPSK信号谱相关密度函数 7.1 实信号模型 BPSK实信号表达式可以写为 r(t)y(t)n(t)r(t) y(t) n(t)r(t)y(t)n(t) s(t)p(t)n(t) s(t)p(t) n(t)s(t)p(t)n(t) ∑n−∞∞a(nT)q(t−…

第十二届蓝桥杯A组省赛填空题Java思路及代码合集(相乘直线货物摆放路径回路计数)

文章目录试题 A: 相乘试题 B: 直线试题 C: 货物摆放试题 D: 路径试题 E: 回路计数试题 A: 相乘 本题总分&#xff1a;5 分 【问题描述】 小蓝发现&#xff0c;他将 1 至 1000000007 之间的不同的数与 2021 相乘后再求除以1000000007 的余数&#xff0c;会得到不同的数。小蓝想…

循环自相关函数和谱相关密度(三)——实信号、复信号模型下的BPSK信号循环谱MATLAB仿真结果及代码

关注公号【逆向通信猿】,循环谱 说明:接上一节循环自相关函数和谱相关密度(二)——实信号、复信号模型下的BPSK信号循环谱推导 7.5 仿真结果 7.5.1 实BPSK信号 符号速率RB = 40,采样率Fs = 960,载波频率fc = 300,符号数N = 1000,矩形成形。

executor线程池框架_如何使用Java 5 Executor框架创建线程池

executor线程池框架Java 5以Executor框架的形式在Java中引入了线程池&#xff0c;它允许Java程序员将任务提交与任务执行分离。 如果要使用Java进行服务器端编程&#xff0c;则线程池是维护系统可伸缩性&#xff0c;鲁棒性和稳定性的重要概念。 对于那些不熟悉Java中的线程池或…

第十二届蓝桥杯A组省赛试题 I: 双向排序(Java)

试题 I: 双向排序 本题总分&#xff1a;25 分 【问题描述】 给定序列 (a1, a2, , an) (1, 2, , n)&#xff0c;即 ai i。 小蓝将对这个序列进行 m 次操作&#xff0c;每次可能是将 a1, a2, , aqi 降序排列&#xff0c; 或者将 aqi , aqi1, , an 升序排列。 请求…

循环自相关函数和谱相关密度(四)——实信号、复信号模型下的QPSK信号循环谱推导

关注公号【逆向通信猿】,口令:循环谱 说明:接上一节循环自相关函数和谱相关密度(三)——实信号、复信号模型下的BPSK信号循环谱MATLAB仿真结果及代码 8 QPSK信号谱相关密度函数 8.1 实信号模型 QPSK实信号表达式可以写为 r ( t ) = y I ( t ) − y Q (

JavaFX技巧29:使布局忽略不可见的节点

在我仍在Swing中实现UI的时候&#xff0c;我曾经是MigLayout的忠实拥护者&#xff08;“一个布局管理者来统治所有这些&#xff0c;对吗Mikael&#xff1f;”&#xff09;。 我真正喜欢的功能之一是当组件不可见时可以定义不同的行为。 MigLayout允许我保留现在不可见的组件所占…

第十一届蓝桥杯A组省赛填空试题 A: 门牌制作(Java)

试题 A: 门牌制作 本题总分&#xff1a;5 分 【问题描述】 小蓝要为一条街的住户制作门牌号。 这条街一共有 2020 位住户&#xff0c;门牌号从 1 到 2020 编号。 小蓝制作门牌的方法是先制作 0 到 9 这几个数字字符&#xff0c;最后根据需要将字符粘贴到门牌上&#xff0c;例如…

循环自相关函数和谱相关密度(五)——实信号、复信号模型下的QPSK信号循环谱MATLAB仿真结果及代码

关注公号【逆向通信猿】口令:循环谱 说明:接上一节循环自相关函数和谱相关密度(四)——实信号、复信号模型下的QPSK信号循环谱推导 8.4 仿真结果 8.4.1 实QPSK信号 符号速率RB = 40,采样率Fs = 960,载波频率fc = 300,符号数N = 1000,矩形成形,二倍载波频率为符号速…

第十一届蓝桥杯A组省赛填空试题 B: 既约分数(Java)

试题 B: 既约分数 本题总分&#xff1a;5 分 【问题描述】 如果一个分数的分子和分母的最大公约数是 1&#xff0c;这个分数称为既约分数。 例如&#xff0c;3/4&#xff0c;5/2&#xff0c;1/8&#xff0c;7/1都是既约分数。 请问&#xff0c;有多少个既约分数&#xff0c;分…

C++判断是否为素数、求一个数的因数、质因数分解

判断一个数是否为素数 #include<iostream> #include<vector> #include<math.h> #include<algorithm>/*判断是否为素数*/ bool isprime(int n) {bool result;int k (int)sqrt((double)n); // 只需要循环到 √n 即可int i 0;for (i 2; i < k; i){…