如何解决Java中的多重继承问题

358 阅读7分钟

Java是当今最流行的面向对象的编程语言之一。

由于它与平台无关,你会在每一种类型的设备和每一个操作系统上发现Java应用程序。由于Java相对容易学习,它是许多程序员最先掌握的语言之一。

你应该熟悉的Java的一个重要特征是类的继承。继承允许程序员通过促进类的重复使用来优化代码。当你可以重复使用已经测试和调试过的代码时,软件开发的生命周期就会变得更短,成本也更低。

虽然理论上是一个简单的概念,但对继承关系进行编码需要注意细节。在多继承方面尤其如此,一个子类继承了多个父类的属性。

Java拒绝多重继承关系,因为它们会产生歧义,但如果你知道该怎么做,有一些方法可以完成许多相同的效果。

在这篇文章中,我们将考虑多重继承的问题,并讨论Java中的其他编码选项。

继承的术语

有时,为了成为一个成功的程序员,你必须学会解决问题,以便为常见的错误或问题找到解决方法。这是安全和聪明地编码的一个必要部分。

一个这样的问题涉及到Java中的多重继承(或者说,缺乏多重继承)。

图片来源

为了充分理解Java中的继承,你需要熟悉基本的面向对象编程(OOP)的继承术语。

  • 类:类 是面向对象编程语言中的一个基本模板结构。一个类定义了一组对象的共同属性。
  • 父类:也被称为基类或超类,父类是一个可扩展的类,为子类提供功能。这就是可重用性发挥作用的地方。父类的定义和功能在创建子类时被重复使用。
  • 子类:更笼统地称为子类,子类继承了另一个类的功能。子类是扩展类或派生类。
  • 继承性:父类和子类之间的关系。

OOP的继承类型

今天有许多流行的面向对象的编程语言在使用,包括Java、C++、JavaScript、Python、PHP、Ruby和Perl。虽然继承是这些OOP语言的共同概念,但并不是每种语言都存在所有的继承类型。

了解一般的继承类型和你所使用的特定语言中对继承的限制是至关重要的。你对继承的了解越多,你就越能成为一个有效的软件开发者。

Java支持的继承类型包括:

  • 单层继承:当一个子类从一个父类派生出特征时。
  • 多级继承:这是单级继承的一个分层形式。在多级继承中,一个子类也可以作为其他子类的父类。每一级之间的关系是线性的--没有像多级继承那样在上面延伸分支。最终的子类就拥有它上面每一级的特征。
  • 分层继承:与多重继承相反。在分层继承中,一个父类有一个以上的子类。因此,与其说它上面有分支,不如说它下面有分支。
  • 混合继承:顾名思义,混合继承是其他继承类型的组合。

除了上述的继承类型,还有一些Java不支持的类型:

  • 多重继承:在多重继承中,一个子类有一个以上的父类。虽然Java和JavaScript不支持多重继承,但C++等OOP语言支持。
  • 多路径继承:多路径继承是多重、多级和分层继承的混合体,在多路径继承中,一个子类从一个父类和父类的几个子类中获得其特征和功能。因为多路径继承依赖于多级继承,所以Java不支持其使用。

为什么Java不支持多路继承?

多重继承的主要问题是,它有可能在子类中产生歧义。在1995年的一份概述白皮书中,Java首席设计师James Gosling说,多继承的问题是创建Java的动机之一。

多重继承的内在困难在钻石问题中体现得最为明显。在钻石问题中,父类A有两个不同的子类B和C;也就是说,子类B和C扩展类A。

图片来源

现在我们创建一个新的子类D,它同时扩展了类B和类C。注意,我们有多重继承(D扩展了B和C),分层继承(B和C扩展了A),以及多级继承(D扩展了A、B和C)。

在钻石问题中,子类B和C从父类A继承了一个方法,B和C都覆盖了这个继承的方法。但是B和C中的新方法相互冲突。

最终子类D从它的多个父类B和C中继承了两个独立且冲突的方法,不清楚D类应该使用哪个方法,所以存在模糊性。其他OOP编程语言实现了各种方法来解决多重继承的歧义。

如何解决Java中的多重继承问题

多重继承有问题并不意味着它没有用。在很多情况下,你可能希望一个类拥有其他几个类的特性。

试想一下,当你成为一个非常成功的软件开发者时,你将购买的那辆特斯拉跑车。它将从跑车类和电动车类中汲取特征。

或者你正在使用一个私人浏览器来阅读这篇文章,它的特征来自在线数据隐私解决方案类和普通互联网浏览器类。

但在Java中你不能扩展多个类。那么,Java是如何处理多重继承的问题的呢?

嗯,它使用了称为接口的结构。接口是一种抽象的类型,它规定了类要实现的行为。因为它们是抽象的,所以接口不包含对其行为的详细说明。相反,类提供了接口行为的具体实现。

接口有几个决定性的特征:

  • 与类不同,你不需要实例化接口。相反,类实现接口
  • 接口只包含公共常量定义和方法标题
  • 接口只能扩展其他接口,不能扩展类
  • 接口可以扩展多个接口,而类可以实现多个接口

现在,我们可以有效地避开接口的钻石问题。回顾一下,只有接口才能扩展其他接口,任何需要多个继承特性的类都必须实现多个接口,我们可以重新定义钻石问题的类。

以前的类A、B、C现在变成了接口A、B、C。接口B和C仍然扩展了接口A,但这些接口中都没有具体的功能,只是定义了行为。D类仍然是一个类,它负责接口B和C中的行为的具体实现。

注意这里的一个关键区别。D类不是在扩展接口B和C,而是在实现它们。所以你实际上并没有多重继承。相反,你只是重新定义了这个问题。

总结

对于任何有效的编码者来说,理解继承是必要的。对于Java程序员来说,了解继承的局限性以及针对多重继承的传统问题的内置Java解决方法同样重要。

学习如何在Java中设置接口来重现多重继承的效果,将提高你的效率和可雇佣性。