【问题标题】:Multiple inheritance in Java or not? [closed]Java中的多重继承与否? [关闭]
【发布时间】:2013-01-19 11:52:27
【问题描述】:

据说,Java 语言只支持单继承。 但是,如何同时从 Object 和任何其他类继承?这不是多重继承吗?

其次,我们为什么需要继承所有 11 个 Object 方法?我几乎无法想象为什么我在 I/O 中需要它们,例如

最后,JDK 8 将为我们提供接口中的默认方法实现,如果这可能会导致 Java 中的多重继承。

如果接口 A 提供具有默认实现的方法 a() 并且接口 B 还提供具有另一个默认实现的 a() 方法,而我们的自定义类 C 实现这两个接口并依赖默认实现,那会不会是Diamond of Death ?

【问题讨论】:

  • 请不要冒犯,但你的意思是你的祖父母也是你的父母。
  • 如果“A”是一个接口,它不能提供方法a()的默认实现。
  • “多重继承”是指一个类可以有多个parents而不是多个ancestors的模型。它与一个类从任何祖先类继承的方法的数量无关。

标签: java class inheritance multiple-inheritance


【解决方案1】:

但是怎么可能继承自 Object 和任何其他 同时上课?这不是多重继承吗?

不,这不是发生的事情。并非所有类都直接从Object 类扩展。但只有继承层次结构顶层的类从Object类扩展(隐式)。层次结构中较低的其余类从Object 类延伸到超类。而且,这就是我们所说的多级继承

因此,请考虑以下层次结构:-

class A { }

class B extends A { }

在上述情况下,class A 等价于class A extends Object

其次,我们为什么需要继承所有 11 个 Object 方法?一世 很难想象为什么我在 I/O 中需要它们

当您说 inherit 时,我怀疑您的意思是 override。您不需要重写 Object 类的任何方法。是否覆盖任何方法都取决于您的要求。例如: - 您经常希望覆盖 equals() 方法,以便为您的实例编写自定义相等测试。在这种情况下,您还应该重写hashCode() 方法,以维护equals()hashCode() 的合同。

最后,JDK 8 将为我们提供默认方法实现 接口,如果这可能会导致多重继承 Java。

如果接口 A 提供具有默认实现的方法 a() 并且 接口 B 还提供了带有另一个默认实现的 a() 方法 我们的自定义类 C 实现了这两个接口并依赖于默认值 意识到——那不是死亡钻石吗?

我无法评论这个概念,因为我还没有读到这件事。可能,我稍后会更新答案。

【讨论】:

  • 每个类都根据 Java 规范扩展 Object。
  • 只回答第一个问题。
  • @hd1。啊!实际上,错过了关键部分。现已更新。
  • @user2033357:这 11 种方法似乎没有任何成本。它不会占用任何额外的内存或任何东西。
  • @user2033357。这并不是说您是否需要某种方法来完成特定任务。在幕后,使用了这些方法。最简单的例子是hashcode 方法。每当您创建一个类的实例时,hashcodedefault implementation 用于为该实例生成hash codes,如果您不覆盖一个。因此,无论如何都需要哈希码。同样,在后台使用了其他方法,您不会及早知道。
【解决方案2】:

但是怎么可能继承自 Object 和任何其他 同时上课?这不是多重继承吗?

除非另有说明,否则类扩展 Object。也就是这个:

class A { ... }

相当于:

class A extends Object { ... }

其次,我们为什么需要继承所有 11 个 Object 方法?一世 很难想象为什么我在 I/O 中需要它们,例如

  • equals()hashCode() 用于比较和哈希表。
  • notify()wait() 构成了跨线程通信的底层基础。
  • getClass() 是所有反射代码的起点。

通过将它们放在Object 上,它们可以用于 JVM 中的每个对象。可以获取any对象的hash码和类,可以检查any两个对象是否相等,可以监控和通知any对象。

如果接口 A 提供具有默认实现的方法 a() 并且 接口 B 还提供了带有另一个默认实现的 a() 方法 我们的自定义类 C 实现了这两个接口并依赖于默认值 意识到——那不是死亡钻石吗?

正如another question here on SO 中所解释的(实际上只是一次搜索“jdk8 默认方法”):

为了解决多重继承问题,一个类实现了两个 为相同方法名提供默认实现的接口 并且签名必须提供方法的实现。

因此,该类必须提供自己的实现,可能委托给默认方法之一。

【讨论】:

  • +1 链接到另一个 SO 问题。
【解决方案3】:

你对“死亡钻石”的看法是正确的,但是......

这是 D 实现接口 C 和 B 而这两个接口都实现 A 的情况。此外,在两个或多个这些接口中定义了默认方法。

在 Java 8 中,他们定义了两种默认方法定义的排序方式。

我记得,如果 A 和 B 都定义了默认方法,那么 D 使用 B 的版本,因为它在类层次结构中较低。

如果 B 和 C 都定义了相同的默认方法,则存在冲突,并且 D 需要自己实现该方法,尽管它可以通过回调在 B 或 C 中实现的版本来实现(或者它可以具有条件和在不同情况下使用两者)。

interface A {  } 
interface B implements A { void m() default {println("In A");} } 
interface C implements A { void m() default {println("In B");} } 
}  
class D implements B, C {  
    public void m() { println("In D"); B.super.m(); } 
} 

但是您可以访问 Oracle 的有关 Java 8 新特性的页面并阅读所有相关信息。我通过谷歌搜索“Java 8 新特性”到达了那里。在http://cr.openjdk.java.net/~briangoetz/lambda/Defender%20Methods%20v4.pdf 找到我的想法

【讨论】:

  • 感谢您的全面回复。现在我明白了这种想法是如何运作的
【解决方案4】:

你继承自一个类,该类继承自对象。 Java 不允许您从两个不同的类链继承。但是,解决这个问题的方法是使用接口。

【讨论】:

  • 只回答第一个问题。
  • 你可以编辑添加第二个问题的答案,伙计
【解决方案5】:

但是怎么可能继承自 Object 和任何其他 同时上课?

你不能这样做,你听错了。

其次,我们为什么需要继承所有 11 个 Object 方法?一世 很难想象为什么我在 I/O 中需要它们,例如

不知道你在说什么。

如果接口 A 提供具有默认实现的方法 a() 并且 接口 B 还提供了带有另一个默认实现的 a() 方法 我们的自定义类 C 实现了这两个接口并依赖于默认值 意识到——那不是死亡钻石吗?

对JDK8一无所知,但是你已经可以在两个接口中实现具有相同名称/类型签名的方法,这可能是不合逻辑的,但Java允许这样做。

【讨论】:

    【解决方案6】:

    首先,Java 中的一切都是对象或原语,所以这里没有问题。 Object 是层次结构顶部的类。

    目前您已经可以将多个接口应用到 Java - 然后您编写您的实现。我想在 Java 8 中,如果你定义了你的接口,那么你就有了实现。如果不是,则使用一些默认值。如果定义了多个默认值(或方法由多个接口声明)- 不使用默认值。可以很简单。

    【讨论】:

      猜你喜欢
      • 2011-12-10
      • 2015-11-11
      • 2012-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-16
      • 2013-02-21
      相关资源
      最近更新 更多