java中的多继承和C++中的多继承问题

先来看看多继承会带来的问题,继承容易导致钻石危机(也称棱形问题),一幅图来说说明:

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

总结如下,主要有两个方面:

(1)如果在一个子类继承的多个父类中拥有相同名字的实例变量,子类在引用该变量时将产生歧义,无法判断应该使用哪个父类的变量。
(2)如果在一个子类继承的多个父类中拥有相同方法,子类中有没有覆盖该方法,那么调用该方法时将产生歧义,无法判断应该调用哪个父类的方法。

在接口中不能有实例变量,只能有静态的常量,不能有具体的方法(包含方法体),只能有抽象方法,因此也就摒弃了多继承的缺点。
对于一个类实现多个接口的情况,因为接口只有抽象方法,具体方法只能由实现接口的类实现,在调用的时候始终只会调用实现类的方法(不存在歧义),因此不存在 多继承的第二个缺点;而又因为接口只有静态的常量,但是由于静态变量是在编译期决定调用关系的,即使存在一定的冲突也会在编译时提示出错;而引用静态变量一般直接使用类名或接口名,从而避免产生歧义,因此也不存在多继承的第一个缺点。
对于一个接口继承多个父接口的情况也一样不存在这些缺点。

但是java中可以用接口和内部类的方式来间接达到多继承的效果:

//这是通过接口来间接实现多继承的

interface HowEat{

public abstract String howeat();

}

class Chenken implements HowEat{

public String howeat(){

return "chicken: fry it ";

}

}

class Orange implements HowEat{

public String howeat(){

return "orangr: make it juice";

}

}

//这是通过内部类来实现的

class Father{

public void output(){

System.out.println("father");

}

}

class Mother{

public void output(){

System.out.println("mather");

}

}

class son{

class Father_son extends Father{

}

class Mother_son extends Mother{

}

public void father(){

(new Father_son()).output();

}

public void mather(){

(new Mother_son()).output();

}

}

时间: 2024-08-02 10:55:31

java中的多继承和C++中的多继承问题的相关文章

(2)java中的集中关系,is a, has a, 继承,重点聊聊继承

java中常见的类关系(javacore上面也有介绍道的) 1.is a关系() 2.has a 整体与局部的关系 3.继承关系 是现实世界中存在而上面两种关系又无法描述的 当然谈的最多的是继承关系,这就出现了,父类和子类.父子类之间有下面一些故事. 父子类中的一般注意事项 子类显示调用父类的构造函数 使用关键字super(), 必须放到子类构造函数的第一行,否则会报错. super和this的区别 super主要是在子类中使用,调用父类的构造方法super(),调用父类的属性方法super.x

java学习中,面向对象的三大特性:封装、继承、多态 以及 super关键字和方法的重写(java 学习中的小记录)

java学习中,面向对象的三大特性:封装.继承.多态 以及 super关键字和方法的重写(java 学习中的小记录) 作者:王可利(Star·星星) 封装     权限修饰符:public 公共的,private 私有的     封装的步骤:          1.使用private 修饰需要封装的成员变量.          2.提供一个公开的方法设置或者访问私有的属性              设置 通过set方法,命名格式:     set属性名();  属性的首字母要大写 访问 通过ge

Swift语言中的属性,方法,下标脚本以及继承

从这篇章节起,Swift编程语言指南大部分的重要内容在于概念,代码并不是太多.理解Swift的面向对象理念,语法以及类结构,构造析构过程对于很好的应用Swift语言将会有比较大的帮助. 属性 存储属性 存储属性通常是那些可以通过直接赋值,或者直接访问成员能够获得的属性类型. 它有些要注意的地方: 若一个结构体被声明为常量,则子属性无法被修改了.在Objective-C中,我们总是无法修改结构体的子属性,但是swift却可以,不过这种情况是个例外,当你存储型属性是个结构体并且是个常量,那你就不要再

android开发中关于继承activity类中方法的调用

android开发中关于继承activity类中的函数,不能在其他类中调用其方法. MainActivity.java package com.example.testmain; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState)

Android(java)学习笔记200:Android中View动画之 XML实现 和 代码实现

1.Animation 动画类型 Android的animation由四种类型组成: XML中: alph 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面转移旋转动画效果 JavaCode中 AlphaAnimation 渐变透明度动画效果 ScaleAnimation 渐变尺寸伸缩动画效果 TranslateAnimation 画面转换位置移动动画效果 RotateAnimation 画面转移旋转动画效果  2.Andro

Java面试题总结(不断更新中)

毕业季,对于程序员来说也是不错的找工作的机会,一份好的简历是打开公司大门的钥匙,但能不能进入自己理想的公司,成为其中的一员,在于面试的成败.本文将介绍一些公司面试时提出的常见的面试题,并做一些简单的回答.也为自己找新工作时,不在去对公司提出的问题去东找西找. 一.Java四大特性:抽象,封装,继承,多态. (1)抽象:从字面意思就可以了解,象就是有点模糊的意思,还没确定好的意思.在面向对象的概念中,我们知道所有的对象都是通过类来描绘的,但是并不是所有的类都是用来描绘对象的,如果一个类中没有包含足

第4节:Java基础 - 必知必会(中)

第4节:Java基础 - 必知必会(中) 本小节是Java基础篇章的第二小节,主要讲述抽象类与接口的区别,注解以及反射等知识点. 一.抽象类和接口有什么区别 抽象类和接口的主要区别可以总结如下: 抽象类中可以没有抽象方法,JDK8版本开始提供了接口总方法的default实现 抽象类和类一样是单继承的:接口可以实现多个父类 抽象类中可以存在普通的成员变量:接口中的变量必须是static final类型的,必须被初始化,接口中只能有常量,没有变量 解析: 在Java中,我们用abstract来定义抽

Java Web学习系列——Maven Web项目中集成使用Spring、MyBatis实现对MySQL的数据访问

本篇内容还是建立在上一篇Java Web学习系列——Maven Web项目中集成使用Spring基础之上,对之前的Maven Web项目进行升级改造,实现对MySQL的数据访问. 添加依赖Jar包 这部分内容需要以下Jar包支持 mysql-connector:MySQL数据库连接驱动,架起服务端与数据库沟通的桥梁: MyBatis:一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架: log4j:Apache的开源项目,一个功能强大的日志组件,提供方便的日志记录: 修改后的pom.xm

JAVA,求m*n阶矩阵中的2*2阶矩阵和的最大值

题目:输入一个m*n阶矩阵,找出m*n阶矩阵中的二阶矩阵和的最大值 输入样例: 1 2 3 0 4;4 3 5 1 2;3 2 4 7 5 输出样例: 17 ------------------------------------------------I am a Dividing line--------------------------------------------- java代码: import java.util.Scanner; /** * m*n阶矩阵中的2*2阶矩阵和最大

友元在继承和传递中的一些问题

声明:①友元关系不能被继承和传递,基类的友元对派生类没有特殊的访问权限,派生类中的友元更不能访问基类中的成员. ②友元不是成员函数,所以不能使用作用域解析符来指出要使用哪个函数.这个问题的解决方法是使用强制类型转换,以便匹配原型时能够选择正确地函数. ③基类的友元能够访问派生类中的基类成分,这是由于自动将派生类转化成了基类,不是因为继承,但是不能访问派生类的非基类成员. 下面通过例子对这几个问题一一说明. #include <stdio.h> #include <stdlib.h>